home *** CD-ROM | disk | FTP | other *** search
/ Aminet 39 / Aminet 39 (2000)(Schatztruhe)[!][Oct 2000].iso / Aminet / game / misc / WormWars.lha / wormwars / source / engine.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-09  |  173.3 KB  |  4,740 lines

  1. /* $Filename: WormWars/Source/engine.c
  2.  * $VER:      WormWars 6.3
  3.  *
  4.  * © Copyright 2000 James R. Jacobs. Freely distributable.
  5.  */
  6.  
  7. #include <string.h>
  8. #include <math.h>
  9. #include <stdio.h>
  10. #include <stdlib.h> /* EXIT_SUCCESS, EXIT_FAILURE */
  11. #include <assert.h>
  12. #define ASSERT
  13.  
  14. #include "stdafx.h"
  15. #include "diff.h"
  16. #include "same.h"
  17. #include "engine.h"
  18.  
  19. /* PRIVATE STRUCTURES -------------------------------------------------- */
  20.  
  21. struct
  22. {   SBYTE x, y, deltax, deltay;
  23.     ABOOL alive, moved, teleported, visible, reflected;
  24. } bullet[9];
  25. struct
  26. {   UWORD freq;
  27.     ULONG score;
  28. } object[LASTOBJECT + 1] =
  29. {   {1280,  60}, // AFFIXER
  30.     {  60,  20}, // AMMO
  31.     { 110,  20}, // ARMOUR
  32.     {  70,  50}, // BIAS
  33.     { 150,  30}, // BOMB
  34.     {  80,  10}, // BONUS
  35.     {1020,  60}, // CLOCK
  36.     { 380,  50}, // CONVERTER
  37.     { 160,  80}, // CUTTER
  38.     { 250,  90}, // CYCLONE
  39.     { 500,  30}, // FREEDOM
  40.     { 320,  50}, // GROWER
  41.     {1900,  90}, // HEALER
  42.     {1360,  60}, // ICE
  43.     { 140,  60}, // LIFE
  44.     { 160,  80}, // LIGHTNING
  45.     { 970,  80}, // MAGNET
  46.     { 240,  40}, // MISSILE
  47.     { 640,  50}, // MULTIPLIER
  48.     { 400,  10}, // NITRO
  49.     { 240,  30}, // POWER
  50.     { 480,  50}, // PROTECTOR
  51.     { 210,  40}, // PULSE
  52.     { 300,  50}, // PUSHER
  53.     { 400,  40}, // REMNANTS
  54.     { 500,  30}, // SIDESHOT
  55.     { 600,  40}, // SLAYER
  56.     { 980,  40}, // SLOWER
  57.     { 730,  70}, // SWITCHER
  58.     { 320,  20}, // TONGUE
  59.     {1400, 120}, // TREASURE
  60.     {3800, 140}  // UMBRELLA
  61. };
  62.  
  63. /*  -200    common
  64.     220-400 uncommon
  65.     420-980 rare
  66.     1000+   very rare */
  67.  
  68. struct
  69. {   SBYTE x, y, deltax, deltay, relx, rely;
  70.     ABOOL alive, last, visible;
  71. } protector[4][PROTECTORS + 1];
  72. struct
  73. {   SBYTE deltax, deltay;
  74. } thewormqueue[4][WORMQUEUELIMIT + 1];
  75. struct
  76. {   SBYTE deltax, deltay;
  77. } thedogqueue[CREATURES + 1][DOGQUEUELIMIT + 1];
  78. struct
  79. {   ABOOL alive;
  80.     SBYTE x, y, player;
  81.     UBYTE object;
  82. } magnet[MAGNETS + 1];
  83.  
  84. SBYTE eachworm[4][2][9] =
  85. { { { GREENHEADUP,   GREENHEADUP,   GREENHEADUP,
  86.       GREENHEADLEFT, ANYTHING,      GREENHEADRIGHT,
  87.       GREENHEADDOWN, GREENHEADDOWN, GREENHEADDOWN
  88.     },
  89.     { GREENMODEUP,   GREENMODEUP,   GREENMODEUP,
  90.       GREENMODELEFT, ANYTHING,      GREENMODERIGHT,
  91.       GREENMODEDOWN, GREENMODEDOWN, GREENMODEDOWN
  92.   } },
  93.   { { REDHEADUP,     REDHEADUP,     REDHEADUP,
  94.       REDHEADLEFT,   ANYTHING,      REDHEADRIGHT,
  95.       REDHEADDOWN,   REDHEADDOWN,   REDHEADDOWN
  96.     },
  97.     { REDMODEUP,     REDMODEUP,     REDMODEUP,
  98.       REDMODELEFT,   ANYTHING,      REDMODERIGHT,
  99.       REDMODEDOWN,   REDMODEDOWN,   REDMODEDOWN
  100.   } },
  101.     {    {    BLUEHEADUP,        BLUEHEADUP,            BLUEHEADUP,
  102.             BLUEHEADLEFT,        ANYTHING,            BLUEHEADRIGHT,
  103.             BLUEHEADDOWN,        BLUEHEADDOWN,        BLUEHEADDOWN
  104.         },
  105.         {    BLUEMODEUP,        BLUEMODEUP,            BLUEMODEUP,
  106.             BLUEMODELEFT,        ANYTHING,            BLUEMODERIGHT,
  107.             BLUEMODEDOWN,        BLUEMODEDOWN,        BLUEMODEDOWN
  108.     }    },
  109.     {    {    YELLOWHEADUP,        YELLOWHEADUP,        YELLOWHEADUP,
  110.             YELLOWHEADLEFT,        ANYTHING,            YELLOWHEADRIGHT,
  111.             YELLOWHEADDOWN,        YELLOWHEADDOWN,        YELLOWHEADDOWN
  112.         },
  113.         {    YELLOWMODEUP,        YELLOWMODEUP,        YELLOWMODEUP,
  114.             YELLOWMODELEFT,        ANYTHING,            YELLOWMODERIGHT,
  115.             YELLOWMODEDOWN,        YELLOWMODEDOWN,        YELLOWMODEDOWN
  116. }    }    };
  117.  
  118. /* Rules for variable types:
  119.  
  120. SBYTE is used for field coordinates and queue indexes
  121. UBYTE is used for field contents
  122. SWORD is used for frequencies
  123. ULONG is used for scores */
  124.  
  125. struct
  126. {   ABOOL alive, explode, visible;
  127.     SBYTE x, y, deltax, deltay, pos, time;
  128.     UBYTE mode, dormant, multi, speed, last, oldlast, species,
  129.           type; // type is relevant worm 0-3 (for drips, missiles and dogs)
  130.     SWORD armour, tongue, freq;
  131.     ULONG score;
  132. } creature[CREATURES + 1];
  133.  
  134. // MODULE VARIABLES (used only within engine.c) ---------------------------
  135.  
  136. MODULE    ABOOL letters[4][LETTERS + 1], trainer;
  137. MODULE  SBYTE freq, ice, lettertype, letterx, lettery, leveltype,
  138.               treasurer;
  139.  
  140. // GLOBAL VARIABLES (owned by engine.c, imported by system.c) -------------
  141.  
  142. ABOOL clearthem  = FALSE,
  143.       modified   = FALSE,
  144.       randomflag = FALSE,
  145.       randomarray[MAXLEVELS + 1];
  146. UBYTE board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  147.       field[FIELDX + 1][FIELDY + 1];
  148. SBYTE a = GAMEOVER,
  149.       players,
  150.       level = 1, levels, reallevel, sourcelevel,
  151.       startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
  152. SWORD secondsleft, secondsperlevel;
  153. TEXT  pathname[81],
  154.       date[DATELENGTH + 1],
  155.       times[TIMELENGTH + 1];
  156. ULONG delay, r;
  157. struct HiScoreStruct  hiscore[HISCORES + 1];
  158. struct TeleportStruct teleport[MAXLEVELS + 1][4];
  159. struct WormStruct     worm[4];
  160.  
  161. /* FUNCTIONS --------------------------------------------------------------
  162.  
  163. NAME        align -- right-justify a string within another string
  164. SYNOPSIS    align(STRPTR, SBYTE, TEXT);
  165. FUNCTION    Moves all text in a string to the right, padding with
  166.             spaces. Does not itself add a null terminator.
  167. INPUTS      string - pointer to the string of text
  168.               size - size in characters of the containing string
  169.             filler - what to pad the left of the string with
  170. NOTE        Null terminators are written over by this function, but that
  171.             does not matter, because calling functions use Text() with an
  172.             explicit length. This function only works with monospaced
  173.             fonts.
  174. MODULE      engine.c */
  175.  
  176. void align(STRPTR string, SBYTE size, TEXT filler)
  177. {   SBYTE i, shift, length;
  178.  
  179.     length = strlen((const char*) string);
  180.     shift = size - length;
  181.     for (i = 1; i <= length; i++)
  182.         *(string + size - i) = *(string + size - i - shift);
  183.     for (i = 0; i <= shift - 1; i++)
  184.         *(string + i) = filler;
  185. }
  186.  
  187. MODULE ABOOL blocked(SBYTE which, SBYTE deltax, SBYTE deltay)
  188. {   UBYTE c = field[xwrap(teleport[level][partner(which)].x + deltax)][ywrap(teleport[level][partner(which)].y + deltay)];
  189.     if ((c < STONE || c > GOAT) && c != METAL)
  190.         return FALSE;
  191.     else return TRUE;
  192. }
  193.  
  194. MODULE void bombblast(SBYTE triggerer, SBYTE player, SBYTE centrex, SBYTE centrey)
  195. {       SBYTE counter, downy, downymax, leftx, leftxmax, rightx, rightxmax, strength, uppy, uppymax, x, y;
  196.         ULONG score = 0;
  197.  
  198.         effect(FXUSE_BOMB);
  199.  
  200.     strength = BOMBADD + (rand() % BOMBRAND);
  201.  
  202.     leftxmax = centrex - strength;
  203.     if (leftxmax < 0)
  204.         leftxmax = 0;
  205.     rightxmax = centrex + strength;
  206.     if (rightxmax > FIELDX)
  207.         rightxmax = FIELDX;
  208.     uppymax = centrey - strength;
  209.     if (uppymax < 0)
  210.         uppymax = 0;
  211.     downymax = centrey + strength;
  212.     if (downymax > FIELDY)
  213.         downymax = FIELDY;
  214.  
  215.     leftx = centrex;
  216.     rightx = centrex;
  217.     uppy = centrey;
  218.     downy = centrey;
  219.     for (counter = 1; counter <= strength; counter++)
  220.     {    if (leftx > leftxmax)
  221.         {    leftx--;
  222.             for (y = uppy; y <= downy; y++)
  223.                 score += squareblast(triggerer, player, field[leftx][y], leftx, y, FALSE);
  224.         }
  225.         if (rightx < rightxmax)
  226.         {    rightx++;
  227.             for (y = uppy; y <= downy; y++)
  228.                 score += squareblast(triggerer, player, field[rightx][y], rightx, y, FALSE);
  229.         }
  230.         if (uppy > uppymax)
  231.         {    uppy--;
  232.             for (x = leftx; x <= rightx; x++)
  233.                 score += squareblast(triggerer, player, field[x][uppy], x, uppy, FALSE);
  234.         }
  235.         if (downy < downymax)
  236.         {    downy++;
  237.             for (x = leftx; x <= rightx; x++)
  238.                 score += squareblast(triggerer, player, field[x][downy], x, downy, FALSE);
  239.     }    }
  240.  
  241.     if (triggerer == HEAD)
  242.         wormscore(player, score);
  243.     elif (triggerer == ORB)
  244.         orbscore(player, score);
  245.     if (worm[player].bias)
  246.         stat(player, LIFE);
  247. }
  248.  
  249. MODULE void bouncegoat(SBYTE which, SBYTE x, SBYTE y)
  250. {   if (field[x][y] == GOAT)
  251.     {   creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  252.         orbscore(which, KILLGOAT);
  253.         change(x, y, BONUS);
  254. }   }
  255.  
  256. MODULE ABOOL bounceorb(SBYTE which, SBYTE x, SBYTE y)
  257. {    if (field[x][y] == METAL)
  258.         return TRUE;
  259.     elif (creature[which].mode == NONE)
  260.     {    if (field[x][y] >= FIRSTNONE && field[x][y] <= LASTNONE)
  261.             return TRUE;
  262.         else return FALSE;
  263.     } elif (creature[which].mode == TONGUE)
  264.     {    if (field[x][y] >= FIRSTTONGUE && field[x][y] <= LASTTONGUE)
  265.             return TRUE;
  266.         else return FALSE;
  267.     } else
  268.     {   // assert(creature[which].mode == ARMOUR);
  269.         if (field[x][y] >= FIRSTARMOUR && field[x][y] <= LASTARMOUR)
  270.             return TRUE;
  271.         else return FALSE;
  272. }   }
  273.  
  274. MODULE SBYTE bsign(SBYTE value)
  275. {   if (value < 0)
  276.         return (-1);
  277.     elif (value > 0)
  278.         return (1);
  279.     else return (0);
  280. }
  281.  
  282. MODULE void changefield(void)
  283. {   SBYTE x, y;
  284.  
  285.     if (randomflag && a == PLAYGAME && level)
  286.     {   do
  287.         {    sourcelevel = (rand() % levels) + 1;
  288.         } while (randomarray[level]);
  289.         randomarray[level] = TRUE;
  290.     } else sourcelevel = level;
  291.  
  292.     for (x = 0; x <= FIELDX; x++)
  293.         for (y = 0; y <= FIELDY; y++)
  294.             field[x][y] = board[sourcelevel][x][y];
  295. }
  296.  
  297. void clearhiscores(void)
  298. {   SBYTE i;
  299.     
  300.     clearthem = FALSE;
  301.     for (i = 0; i <= HISCORES; i++)
  302.     {   hiscore[i].player = -1;
  303.         hiscore[i].level = 0;
  304.         hiscore[i].score = 0;
  305.         hiscore[i].fresh = FALSE;
  306.         hiscore[i].name[0] = 0;
  307.         hiscore[i].time[0] = 0;
  308.         hiscore[i].date[0] = 0;
  309. }   }
  310.  
  311. MODULE void clearletters(void)
  312. {   SBYTE player, which;
  313.  
  314.     for (player = 0; player <= 3; player++)
  315.         for (which = 0; which <= LETTERS; which++)
  316.         {   letters[player][which] = FALSE;
  317.             drawletter(player, FIRSTLETTER + which, BLACK);
  318. }       }
  319.  
  320. MODULE void copyfield(SBYTE source, SBYTE destination)
  321. {   SBYTE which, x, y;
  322.  
  323.     for (x = 0; x <= FIELDX; x++)
  324.         for (y = 0; y <= FIELDY; y++)
  325.             board[destination][x][y] = board[source][x][y];
  326.     startx[destination] = startx[source];
  327.     starty[destination] = starty[source];
  328.     for (which = 0; which <= 1; which++)
  329.     {   teleport[destination][which].alive = teleport[source][which].alive;
  330.         teleport[destination][which].x     = teleport[source][which].x;
  331.         teleport[destination][which].y     = teleport[source][which].y;
  332. }   }
  333.  
  334. MODULE void death(void)
  335. {   SBYTE pain, player, which;
  336.     ABOOL slow;
  337.  
  338.     for (player = 0; player <= 3; player++)
  339.     {   if (worm[player].lives)
  340.         {   if (!worm[player].alive)
  341.             {   slow = FALSE;
  342.                 pain = 0;
  343.                 if (worm[player].cause >= FIRSTTAIL && worm[player].cause <= LASTTAIL)
  344.                 {   if (player == worm[player].cause - FIRSTTAIL)
  345.                         pain = TAILPAIN;
  346.                     else pain = OTHERTAILPAIN;
  347.                     slow = TRUE;
  348.                 } elif (worm[player].cause >= FIRSTFIRE && worm[player].cause <= LASTFIRE)
  349.                     pain = WORMFIREPAIN;
  350.                 elif (worm[player].cause >= FIRSTHEAD && worm[player].cause <= LASTHEAD)
  351.                     pain = HEADPAIN;
  352.                 elif (worm[player].cause >= FIRSTPROTECTOR && worm[player].cause <= LASTPROTECTOR)
  353.                     pain = PROTECTORPAIN;
  354.                 elif (worm[player].cause >= FIRSTMISSILE && worm[player].cause <= LASTMISSILE)
  355.                     pain = MISSILEPAIN;
  356.                 elif (worm[player].cause >= FIRSTDRIP && worm[player].cause <= LASTDRIP)
  357.                     pain = DRIPPAIN;
  358.                 else switch (worm[player].cause)
  359.                 {
  360.                 case BOMB:
  361.                     pain = BOMBPAIN;
  362.                 break;
  363.                 case WOOD:
  364.                     pain = WOODPAIN;
  365.                     slow = TRUE;
  366.                 break;
  367.                 case FRAGMENT:
  368.                     pain = FRAGMENTPAIN;
  369.                 break;
  370.                 case GOAT:
  371.                     pain = GOATPAIN;
  372.                     slow = TRUE;
  373.                 break;
  374.                 case SLAYER:
  375.                     pain = SLAYERPAIN;
  376.                 break;
  377.                 case STONE:
  378.                     pain = STONEPAIN;
  379.                     slow = TRUE;
  380.                 break;
  381.                 case TELEPORT:
  382.                     pain = TELEPORTPAIN;
  383.                     slow = TRUE;
  384.                 break;
  385.                 case SLIME:
  386.                     pain = SLIMEPAIN;
  387.                     slow = TRUE;
  388.                 break;
  389.                 case METAL:
  390.                     pain = METALPAIN;
  391.                     slow = TRUE;
  392.                 break;
  393.                 case REMNANTS:
  394.                     pain = REMNANTPAIN;
  395.                     slow = TRUE;
  396.                 break;
  397.                 case LIGHTNING:
  398.                     pain = LIGHTNINGPAIN;
  399.                 break;
  400.                 case PENGUIN:
  401.                     pain = PENGUINPAIN;
  402.                 break;
  403.                 case WHIRLWIND:
  404.                     pain = WHIRLWINDPAIN;
  405.                 break;
  406.                 case DOG:
  407.                     pain = DOGPAIN;
  408.                 break;
  409.                 case CLOUD:
  410.                     pain = CLOUDPAIN;
  411.                 break;
  412.                 case ORB:
  413.                     pain = ORBPAIN;
  414.                 break;
  415.                 default:
  416.                     // assert(0);
  417.                 break;
  418.                 }
  419.                 if (worm[player].victor >= 0 && worm[player].victor != player)
  420.                 {   wormscore(worm[player].victor, KILLWORM);
  421.                     if (worm[worm[player].victor].bias)
  422.                     {   worm[worm[player].victor].lives += pain;
  423.                         stat(worm[player].victor, LIFE);
  424.                 }   }
  425.                 if (slow)
  426.                 {   worm[player].speed = slowdown(worm[player].speed, worm[player].nitro);
  427.                     stat(player, NITRO); 
  428.                 }
  429.                 if (pain > worm[player].lives)
  430.                     worm[player].lives = 0;
  431.                 else worm[player].lives -= pain;
  432.                 draw(worm[player].x, worm[player].y, SKULL);
  433.                 drawcause(player, NORMAL);
  434.                 stat(player, LIFE);
  435.                 if (level)
  436.                     worm[player].levelreached = level;
  437.                 else worm[player].levelreached = reallevel;
  438.                 if (worm[player].lives)
  439.                 {   effect(FXPAIN + player);
  440.                     worm[player].alive = TRUE;
  441.                     worm[player].causewait = r + CAUSEWAIT;
  442.                 } else
  443.                 {   /* kill worm */
  444.                     effect(FXDEATH_WORM);
  445.                     if (ice == player)
  446.                         ice = -1;
  447.                     field[worm[player].x][worm[player].y] = SKULL;
  448.                     for (which = 0; which <= PROTECTORS; which++)
  449.                         if (protector[player][which].alive && protector[player][which].visible)
  450.                             change(protector[player][which].x, protector[player][which].y, EMPTY);
  451.                     for (which = 0; which <= MAGNETS; which++)
  452.                         if (magnet[which].player == player)
  453.                             magnet[which].alive = FALSE;
  454.                     if (worm[player].score >= worm[player].hiscore)
  455.                         worm[player].hiscore = worm[player].score;
  456.     }   }   }   }
  457.  
  458.     if (!worm[0].lives && !worm[1].lives && !worm[2].lives && !worm[3].lives)
  459.     {   /* End of game */
  460.         for (player = 0; player <= 3; player++)
  461.             if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
  462.                 worm[player].hiscore = worm[player].score;
  463.         newhiscores();
  464.         effect(FXGAMEOVER);
  465.         a = GAMEOVER;
  466.         if (players == 1)
  467.             say((STRPTR) "Game over!", worm[onlyworm(FALSE)].colour);
  468.         elif (worm[0].control && ((!worm[1].control) || worm[1].score < worm[0].score) && ((!worm[2].control) || worm[2].score < worm[0].score) && ((!worm[3].control) || worm[3].score < worm[0].score))
  469.             say((STRPTR) "Green wins!", GREEN);
  470.         elif (worm[1].control && ((!worm[0].control) || worm[0].score < worm[1].score) && ((!worm[2].control) || worm[2].score < worm[1].score) && ((!worm[3].control) || worm[3].score < worm[1].score))
  471.             say((STRPTR) "Red wins!", RED);
  472.         elif (worm[2].control && ((!worm[0].control) || worm[0].score < worm[2].score) && ((!worm[1].control) || worm[1].score < worm[2].score) && ((!worm[3].control) || worm[3].score < worm[2].score))
  473.             say((STRPTR) "Blue wins!", BLUE);
  474.         elif (worm[3].control && ((!worm[0].control) || worm[0].score < worm[3].score) && ((!worm[1].control) || worm[1].score < worm[3].score) && ((!worm[2].control) || worm[2].score < worm[3].score))
  475.             say((STRPTR) "Yellow wins!", YELLOW);
  476.         else say((STRPTR) "A draw!", WHITE);
  477.         waitasec();
  478.         anykey(FALSE);
  479. }   }
  480.  
  481. MODULE void drawcause(SBYTE player, SBYTE state)
  482. {    if (state == BLACK)
  483.         draw(-2 + ((FIELDX + 4) * worm[player].statx), (FIELDY / 2) - CAUSEYDISTANCE + (worm[player].staty * CAUSEYDISTANCE * 2), BLACKENED);
  484.     else draw(-2 + ((FIELDX + 4) * worm[player].statx), (FIELDY / 2) - CAUSEYDISTANCE + (worm[player].staty * CAUSEYDISTANCE * 2), worm[player].cause);
  485. }
  486.  
  487. MODULE void drawletter(SBYTE player, SBYTE letter, SBYTE state)
  488. {   UBYTE c;
  489.     
  490.     if (state == BLACK)
  491.         c = BLACKENED;
  492.     else c = letter;
  493.     if (!worm[player].statx)
  494.         if (!worm[player].staty)
  495.             draw(-7 + ((letter - FIRSTLETTER) % 4),
  496.                  (FIELDY / 2) - 2 + ((letter - FIRSTLETTER) / 4),
  497.                  c);
  498.         else
  499.             draw(-7 + ((letter - FIRSTLETTER) % 4),
  500.                  (FIELDY / 2) + 1 + ((letter - FIRSTLETTER) / 4),
  501.                  c);
  502.     elif (!worm[player].staty)
  503.         draw(FIELDX + 4 + ((letter - FIRSTLETTER) % 4),
  504.              (FIELDY / 2) - 2 + ((letter - FIRSTLETTER) / 4),
  505.              c);
  506.     else
  507.         draw(FIELDX + 4 + ((letter - FIRSTLETTER) % 4),
  508.              (FIELDY / 2) + 1 + ((letter - FIRSTLETTER) / 4),
  509.              c);
  510. }
  511.  
  512. /* NAME     enginesetup -- once-only initialization of engine variables
  513. SYNOPSIS    enginesetup(void);
  514. FUNCTION    Sets up the unchanging worm variables.
  515. MODULE      engine.c */
  516.  
  517. void enginesetup(void)
  518. {   worm[0].statx = worm[0].staty = worm[1].staty = worm[2].statx = 0;
  519.     worm[1].statx = worm[2].staty = worm[3].statx = worm[3].staty = 1;
  520.     worm[0].colour = GREEN;
  521.     worm[1].colour = RED;
  522.     worm[2].colour = BLUE;
  523.     worm[3].colour = YELLOW;
  524.     worm[0].name[0] = worm[1].name[0] = worm[2].name[0] = worm[3].name[0] = 0;
  525.  
  526.     strcpy(pathname, DEFAULTSET);
  527.  
  528.     systemsetup();
  529. }
  530.  
  531. /* NAME     fastloop -- things done often
  532. SYNOPSIS    fastloop(void);
  533. FUNCTION    Checks for and handles level completion.
  534. MODULE      engine.c */
  535.  
  536. MODULE void fastloop(void)
  537. {   ABOOL complete;
  538.     SBYTE advancer = -1, player, which;
  539.  
  540.     /* update joystick `1' */
  541.     joy0();
  542.  
  543.     /* flash letter */
  544.     if (level)
  545.         if (r % 8 == 1)
  546.             draw(letterx, lettery, WHITENED);
  547.         elif (r % 8 == 2)
  548.             draw(letterx, lettery, lettertype);
  549.  
  550.     // flash icons
  551.  
  552.     for (player = 0; player <= 3; player++)
  553.     {    icon(player, ICE);
  554.         icon(player, FREEDOM);
  555.         icon(player, CUTTER);
  556.     }
  557.  
  558.     /* handle level completion */
  559.     for (player = 0; player <= 3; player++)
  560.     {   complete = TRUE;
  561.         for (which = 0; which <= LETTERS; which++)
  562.             if (!letters[player][which])
  563.                 complete = FALSE;
  564.         if (complete)
  565.             advancer = player;
  566.     }
  567.     if (advancer != -1)
  568.     {   if (level++ == 0)
  569.         {   level = reallevel + 1;
  570.             reallevel = 0;
  571.         }
  572.         stopfx();
  573.         if (level > levels)
  574.             effect(FXCELEBRATE);
  575.         newlevel(advancer);
  576. }   }
  577.  
  578. void fillfield(SBYTE which)
  579. {    SBYTE x, y;
  580.  
  581.     for (x = 0; x <= FIELDX; x++)
  582.         for (y = 0; y <= FIELDY; y++)
  583.         {    board[level][x][y] = which;
  584.             draw(x, y, which);
  585.         }
  586.     board[level][startx[level]][starty[level]] = EMPTY;
  587.     draw(startx[level], starty[level], START);
  588.     if (teleport[level][0].alive)
  589.     {    board[level][teleport[level][0].x][teleport[level][0].y] = TELEPORT;
  590.         draw(teleport[level][0].x, teleport[level][0].y, ONE);
  591.     }
  592.     if (teleport[level][1].alive)
  593.     {    board[level][teleport[level][1].x][teleport[level][1].y] = TELEPORT;
  594.         draw(teleport[level][1].x, teleport[level][1].y, TWO);
  595. }    }
  596.  
  597. MODULE ABOOL findempty(SBYTE* x, SBYTE* y, SBYTE first, SBYTE last)
  598. {    SBYTE count = 0, xx, yy;
  599.  
  600.     do
  601.     {    xx = rand() % (FIELDX + 1);
  602.         yy = rand() % (FIELDY + 1);
  603.     } while ((field[xx][yy] < first || field[xx][yy] > last) && ++count < PATIENCE);
  604.     if (count < PATIENCE)
  605.     {    *x = xx;
  606.         *y = yy;
  607.         return(TRUE);
  608.     } else return(FALSE);
  609. }
  610.  
  611. void gameloop(void)
  612. {   SBYTE i, player;
  613.  
  614.     if (a == PLAYGAME)
  615.     {   fastloop();
  616.         gameinput();
  617.     }
  618.     if (a == PLAYGAME)
  619.         for (player = 0; player <= 3; player++)
  620.             if (worm[player].lives && (!(r % worm[player].speed)) && (ice == -1 || ice == player))
  621.                 wormloop(player);
  622.     joy0();
  623.     if (a == PLAYGAME)
  624.         for (i = 0; i <= CREATURES; i++)
  625.             if (creature[i].alive && (!(r % creature[i].speed)) && (ice == -1 || (creature[i].species == MISSILE && ice == creature[i].type)))
  626.                 creatureloop(i);
  627.     joy0();
  628.     if (a == PLAYGAME && !(r % MAGNETSPEED))
  629.         magnetloop();
  630.     joy0();
  631.     if (a == PLAYGAME)
  632.         death();
  633.     joy0();
  634.     if (a == PLAYGAME && !(r % VERYSLOW))
  635.         slowloop();
  636.     joy0();
  637.     timing();
  638. }
  639.  
  640. MODULE void killall(void)
  641. {   UBYTE i;
  642.  
  643.     for (i = 0; i <= CREATURES; i++)
  644.         creature[i].alive = FALSE;
  645.     for (i = 0; i <= MAGNETS; i++)
  646.         magnet[i].alive = FALSE;
  647.     teleport[level][2].alive = FALSE;
  648.     teleport[level][3].alive = FALSE;
  649. }
  650.  
  651. void levelappend(void)
  652. {    UBYTE oldlevel;
  653.  
  654.     if (levels < MAXLEVELS)
  655.     {    oldlevel = level;
  656.         level = ++levels;
  657.         newfield();
  658.         level = oldlevel;
  659.         saylevel(WHITE);
  660. }    }
  661.  
  662. void leveldelete(void)
  663. {    SBYTE i;
  664.  
  665.     /* pull boards
  666.  */
  667.  
  668.     if (levels > 1)
  669.     {    if (level < levels)
  670.             for (i = level; i < levels; i++)
  671.                 copyfield(i + 1, i);
  672.         else
  673.             level--;
  674.         levels--;
  675.         saylevel(WHITE);
  676.         turborender();
  677. }    }
  678.  
  679. void levelerase(void)
  680. {    newfield();
  681.     turborender();
  682. }
  683.  
  684. void levelinsert(void)
  685. {    SBYTE i;
  686.  
  687.     /* push boards
  688.  */
  689.  
  690.     if (levels < MAXLEVELS)
  691.     {    for (i = levels; i >= level; i--)
  692.             copyfield(i, i + 1);
  693.         levels++;
  694.         saylevel(WHITE);
  695.         newfield();
  696.         turborender();
  697. }    }
  698.  
  699. SBYTE loadfields(STRPTR fieldname)
  700. {   SBYTE i, j, x, y;
  701.     TEXT  IOBuffer[NAMELENGTH + 1];
  702.     UBYTE ver;
  703.  
  704.     /* This routine is not entirely robust, especially regarding
  705.     failures part way through reading. Also, field data values must be
  706.     those supported by the field editor (ie. objects, and the squares
  707.     represented by F1-F8), or undefined behaviour may result. None of
  708.     this is currently checked for. Provided that the fieldset was
  709.     created with the official field editor, and the file is not
  710.     corrupt, these failures should never happen anyway.
  711.  
  712.     open file */
  713.  
  714.     // say("Opening...", WHITE);
  715.  
  716.     if (!ZOpen(fieldname, FALSE))
  717.         return 1; /* no harm done */
  718.  
  719.     /* read header */
  720.  
  721.     // say("Reading header...", WHITE);
  722.  
  723.     if (!ZRead(IOBuffer, 10))
  724.     {    ZClose();
  725.         return 2; /* no harm done */
  726.     }
  727.     if (!strcmp(IOBuffer, "FSET 6.3"))
  728.         ver = 63;
  729.     elif (!strcmp(IOBuffer, "FSET 6.2"))
  730.         ver = 62;
  731.     elif (!strcmp(IOBuffer, "FSET 6.0"))
  732.         ver = 60;
  733.     elif (!strcmp(IOBuffer, "FSET 5.6"))
  734.         ver = 56;
  735.     elif (!strcmp(IOBuffer, "FSET 5.5"))
  736.         ver = 55;
  737.     elif (!strcmp(IOBuffer, "FSET 5.3"))
  738.         ver = 53;
  739.     elif (!strcmp(IOBuffer, "FSET 5.1"))
  740.         ver = 51;
  741.     elif (!strcmp(IOBuffer, "FSET 5.0"))
  742.         ver = 50;
  743.     elif (!strcmp(IOBuffer, "FSET 4.4"))
  744.         ver = 44;
  745.     else
  746.     {   ZClose();
  747.         return 3; /* no harm done */
  748.     }
  749.     levels = IOBuffer[9];
  750.  
  751.     /* read high score table */
  752.  
  753.     // say("Reading high score table...", WHITE);
  754.  
  755.     for (i = 0; i <= HISCORES; i++)
  756.     {    if (!ZRead(IOBuffer, 6))
  757.         {    ZClose();
  758.             return 4; /* incorrect levels */
  759.         }
  760.         hiscore[i].fresh            =  FALSE;
  761.         hiscore[i].player            =  IOBuffer[0];
  762.         hiscore[i].level            =  IOBuffer[1];
  763.         hiscore[i].score            = (IOBuffer[2] * 16777216)
  764.                                     + (IOBuffer[3] * 65536)
  765.                                     + (IOBuffer[4] * 256)
  766.                                     +  IOBuffer[5];
  767.  
  768.         if (!ZRead(IOBuffer, NAMELENGTH + 1))
  769.         {    ZClose();
  770.             return 5; /* incorrect levels, corrupted high scores */
  771.         }
  772.         for (j = 0; j <= NAMELENGTH; j++)
  773.             hiscore[i].name[j]        = IOBuffer[j];
  774.  
  775.         if (ver >= 50)
  776.         {    if (!ZRead(IOBuffer, TIMELENGTH + 1))
  777.             {    ZClose();
  778.                 return 6; /* incorrect levels, corrupted high scores */
  779.             }
  780.             for (j = 0; j <= TIMELENGTH; j++)
  781.                 hiscore[i].time[j]    = IOBuffer[j];
  782.  
  783.             if (!ZRead(IOBuffer, DATELENGTH + 1))
  784.             {    ZClose();
  785.                 return 7; /* incorrect levels, corrupted high scores */
  786.             }
  787.             for (j = 0; j <= DATELENGTH; j++)
  788.                 hiscore[i].date[j]    = IOBuffer[j];
  789.         } else
  790.         {    /* skip extra name character */
  791.  
  792.             if (!ZRead(IOBuffer, 1))
  793.             {    ZClose();
  794.                 return 8; /* incorrect levels, corrupted high scores */
  795.             } else
  796.             {    if (hiscore[i].name[0])
  797.                 {    strcpy(hiscore[i].time, "??:??");
  798.                     strcpy(hiscore[i].date, "??/??/??");
  799.                 } else
  800.                 {    hiscore[i].time[0] = 0;
  801.                     hiscore[i].date[0] = 0;
  802.     }    }    }    }
  803.  
  804.     // say("Reading level data...", WHITE);
  805.  
  806.     /* read level data */
  807.  
  808.     for (i = 0; i <= levels; i++)
  809.     {   if (!ZRead(IOBuffer, 8))
  810.         {   ZClose();
  811.             return 9;
  812.             /* incorrect levels, corrupted high scores,
  813.             incorrect startx, teleports, field data */
  814.         }
  815.         startx[i]            =  IOBuffer[0];
  816.         starty[i]            =  IOBuffer[1];
  817.         teleport[i][0].alive =  IOBuffer[2];
  818.         teleport[i][0].x     =  IOBuffer[3];
  819.         teleport[i][0].y     =  IOBuffer[4];
  820.         teleport[i][1].alive =  IOBuffer[5];
  821.         teleport[i][1].x     =  IOBuffer[6];
  822.         teleport[i][1].y     =  IOBuffer[7];
  823.  
  824.         if (!ZRead((char *) &board[i][0][0], (FIELDX + 1) * (FIELDY + 1)))
  825.         {   ZClose();
  826.             return 10;
  827.             /* incorrect levels, corrupted high scores,
  828.             incorrect startx, teleports, field data */
  829.         } else
  830.         {   if (ver <= 44)
  831.             {   // convert from FSET 4.4 to FSET 5.0 format
  832.                 for (x = 0; x <= FIELDX; x++)
  833.                     for (y = 0; y <= FIELDY; y++)
  834.                         if (board[i][x][y] >= 16)
  835.                             board[i][x][y] += 2;
  836.             }
  837.             if (ver <= 50)
  838.             {   // convert from FSET 5.0 to FSET 5.1 format
  839.                 for (x = 0; x <= FIELDX; x++)
  840.                      for (y = 0; y <= FIELDY; y++)
  841.                           if (board[i][x][y] >= 11)
  842.                               board[i][x][y]++;
  843.             }
  844.             if (ver <= 51)
  845.             {   // convert from FSET 5.1 to FSET 5.3 format
  846.                 for (x = 0; x <= FIELDX; x++)
  847.                     for (y = 0; y <= FIELDY; y++)
  848.                         if (board[i][x][y] >= 7 && board[i][x][y] <= 63)
  849.                             board[i][x][y]++;
  850.             }
  851.             if (ver <= 53)
  852.             {   // convert from FSET 5.3 to FSET 5.5 format
  853.                 for (x = 0; x <= FIELDX; x++)
  854.                     for (y = 0; y <= FIELDY; y++)
  855.                         if (board[i][x][y] >= 20)
  856.                             board[i][x][y]++;
  857.             }
  858.             if (ver <= 55)
  859.             {   // convert from FSET 5.5 to FSET 5.6 format
  860.                 for (x = 0; x <= FIELDX; x++)
  861.                     for (y = 0; y <= FIELDY; y++)
  862.                         if (board[i][x][y] >= 13)
  863.                             board[i][x][y]++;
  864.             }
  865.             if (ver <= 56)
  866.             {   // convert from FSET 5.6 to FSET 6.0 format
  867.                 for (x = 0; x <= FIELDX; x++)
  868.                     for (y = 0; y <= FIELDY; y++)
  869.                         if (board[i][x][y] >= 8 && board[i][x][y] <= 20)
  870.                             board[i][x][y]++;
  871.                         elif (board[i][x][y] >= 21)
  872.                             board[i][x][y] += 2;
  873.             }
  874.             if (ver <= 60)
  875.             {   // convert from FSET 6.0 to FSET 6.2 format
  876.                 for (x = 0; x <= FIELDX; x++)
  877.                     for (y = 0; y <= FIELDY; y++)
  878.                         if (board[i][x][y] >= 7)
  879.                             board[i][x][y]++;
  880.             }
  881.             if (ver <= 62)
  882.             {   // convert from FSET 6.2 to FSET 6.3 format
  883.                 for (x = 0; x <= FIELDX; x++)
  884.                     for (y = 0; y <= FIELDY; y++)
  885.                         if (board[i][x][y] >= 7)
  886.                             board[i][x][y]++;
  887.     }   }   }
  888.  
  889.     // say("Open done.", WHITE);
  890.  
  891.     // no need to read version string
  892.     ZClose();
  893.     modified = FALSE;
  894.     return 0;
  895. }
  896.  
  897. MODULE void magnetloop(void)
  898. {   SBYTE i;
  899.     UBYTE c;
  900.  
  901.     for (i = 0; i <= MAGNETS; i++)
  902.         if (magnet[i].alive)
  903.         {   // defensive programming to ensure magnet is still valid
  904.             if (field[magnet[i].x][magnet[i].y] != magnet[i].object)
  905.                 magnet[i].alive = FALSE;
  906.             else
  907.             {   change(magnet[i].x, magnet[i].y, EMPTY);
  908.                 magnet[i].x += bsign(worm[magnet[i].player].x - magnet[i].x);
  909.                 magnet[i].y += bsign(worm[magnet[i].player].y - magnet[i].y);
  910.                 c = field[magnet[i].x][magnet[i].y];
  911.            
  912.                 if ((c >= FIRSTEMPTY && c <= LASTEMPTY)
  913.                  || (c >= FIRSTTAIL  && c <= LASTTAIL))
  914.                     change(magnet[i].x, magnet[i].y, magnet[i].object);
  915.                 elif (c >= FIRSTHEAD && c <= LASTHEAD)
  916.                 {   change(magnet[i].x, magnet[i].y, magnet[i].object);
  917.                     wormscore(c - FIRSTHEAD, wormobject(c - FIRSTHEAD, magnet[i].x, magnet[i].y));
  918.                     change(magnet[i].x, magnet[i].y, FIRSTHEAD + magnet[i].player); // not entirely the right head image
  919.                 } else magnet[i].alive = FALSE;
  920. }       }   }
  921.  
  922. void matchteleports(void)
  923. {    SBYTE which;
  924.  
  925.     for (which = 0; which <= levels; which++)
  926.         if (teleport[which][0].alive == TRUE && teleport[which][1].alive == FALSE)
  927.         {    board[which][teleport[which][0].x][teleport[which][0].y] = EMPTY;
  928.             teleport[which][0].alive = FALSE;
  929.             if (level == which && a == FIELDEDIT)
  930.                 draw(teleport[which][0].x, teleport[which][0].y, EMPTY);
  931.         } elif (teleport[which][0].alive == FALSE && teleport[which][1].alive == TRUE)
  932.         {    board[which][teleport[which][1].x][teleport[which][1].y] = EMPTY;
  933.             teleport[which][1].alive = FALSE;
  934.             if (level == which && a == FIELDEDIT)
  935.                 draw(teleport[which][1].x, teleport[which][1].y, EMPTY);
  936. }        }
  937.  
  938. MODULE void newfield(void)
  939. {    int x, y;
  940.  
  941.     teleport[level][0].alive = FALSE;
  942.     teleport[level][1].alive = FALSE;
  943.     startx[level] = FIELDX / 2;
  944.     starty[level] = FIELDY / 2;
  945.  
  946.     if (level)
  947.         for (x = 0; x <= FIELDX; x++)
  948.             for (y = 0; y <= FIELDY; y++)
  949.                 board[level][x][y] = EMPTY;
  950.     else for (x = 0; x <= FIELDX; x++)
  951.         for (y = 0; y <= FIELDY; y++)
  952.             board[0][x][y] = SILVER;
  953. }
  954.  
  955. void newfields(void)
  956. {   if (verify())
  957.     {   strcpy(pathname, DEFAULTSET);
  958.         levels = DEFAULTLEVELS;
  959.         modified = FALSE;
  960.         for (level = 0; level <= levels; level++)
  961.             newfield();
  962.         clearhiscores();
  963.         level = 1;
  964.         if (a == FIELDEDIT)
  965.         {    turborender();
  966.             saylevel(WHITE);
  967.         } else hiscores();
  968. }    }
  969.  
  970. void newgame(void)
  971. {   SBYTE i, player;
  972.  
  973.     players = 0;
  974.     for (player = 0; player <= 3; player++)
  975.     {   if (worm[player].control != NONE)
  976.             players++;
  977.         worm[player].lives = 0;
  978.         worm[player].speed = NORMAL;
  979.         worm[player].hiscore = 0;
  980.     }
  981.     for (i = 1; i <= MAXLEVELS; i++)
  982.        randomarray[i] = FALSE;
  983.  
  984.     r         = -1;
  985.     trainer   = FALSE;
  986.     ice       = -1;
  987.     reallevel = 0;
  988.  
  989.     level     = 1;
  990.     a         = PLAYGAME;
  991.     clearscreen();
  992.     newlevel(rand() % 4);
  993.     timing();
  994. }
  995.  
  996. MODULE void newhiscores(void)
  997. {   PERSIST TEXT  amiganame[4][NAMELENGTH + 1] = {"Jay Miner", "Carl Sassenrath", "R. J. Mical", "Dave Morse"};
  998.     AUTO    SBYTE i, j, player;
  999.  
  1000.     datestamp();
  1001.     for (player = 0; player <= 3; player++)
  1002.         for (i = 0; i <= HISCORES; i++)
  1003.             if (worm[player].control != NONE && worm[player].score >= hiscore[i].score)
  1004.             {   /* push all worse hiscores down */
  1005.  
  1006.                 if (i < HISCORES)
  1007.                     for (j = HISCORES; j >= i + 1; j--)
  1008.                     {   hiscore[j].player     = hiscore[j - 1].player;
  1009.                         hiscore[j].level      = hiscore[j - 1].level;
  1010.                         hiscore[j].score      = hiscore[j - 1].score;
  1011.                         hiscore[j].fresh      = hiscore[j - 1].fresh;
  1012.                         strcpy(hiscore[j].name, hiscore[j - 1].name);
  1013.                         strcpy(hiscore[j].date, hiscore[j - 1].date);
  1014.                         strcpy(hiscore[j].time, hiscore[j - 1].time);
  1015.                     }
  1016.                 modified = TRUE;
  1017.                 hiscore[i].player = player;
  1018.                 hiscore[i].level  = worm[player].levelreached;
  1019.                 hiscore[i].score  = worm[player].hiscore;
  1020.                 if (worm[player].control == AMIGA)
  1021.                 {   strcpy(hiscore[i].name, amiganame[player]);
  1022.                     hiscore[i].fresh = FALSE;
  1023.                 } else
  1024.                 {   // assert(worm[player].control == HUMAN);
  1025.                     strcpy(hiscore[i].name, "(New)");
  1026.                     hiscore[i].fresh = TRUE;
  1027.                 }
  1028.                 strcpy(hiscore[i].time, times);
  1029.                 strcpy(hiscore[i].date, date);
  1030.                 break; /* vital */
  1031. }           }
  1032.  
  1033. MODULE void newlevel(SBYTE player)
  1034. {   SBYTE i, j;
  1035.  
  1036.     if (level >= 2)
  1037.         rundown(player);
  1038.     if (a == PLAYGAME)
  1039.     {   if (level > levels)
  1040.         {   for (i = 0; i <= 3; i++)
  1041.             {   if (worm[i].lives)
  1042.                     worm[i].levelreached = -1;
  1043.                 if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
  1044.                     worm[player].hiscore = worm[player].score;
  1045.             }
  1046.             celebrate();
  1047.             newhiscores();
  1048.             titlescreen();
  1049.         } else
  1050.         {   saylevel(WHITE);
  1051.             for (i = 0; i <= 3; i++)
  1052.             {   worm[i].multi = (SBYTE) atleast(worm[i].multi / 2, 1);
  1053.                 worm[i].remnants = FALSE;
  1054.             }
  1055.             killall();
  1056.             clearletters();
  1057.             changefield();
  1058.             for (i = 0; i <= 3; i++)
  1059.             {   worm[i].speed = NORMAL;
  1060.         if (worm[i].lives)
  1061.             stat(i, NITRO);
  1062.         worm[i].moved = FALSE;
  1063.         worm[i].x = startx[sourcelevel];
  1064.         worm[i].y = starty[sourcelevel];
  1065.         switch(i)
  1066.         {
  1067.         case 0:
  1068.             worm[0].deltax = -1;
  1069.             worm[0].deltay = 0;
  1070.         break;
  1071.         case 1:
  1072.             worm[1].deltax = 1;
  1073.             worm[1].deltay = 0;
  1074.         break;
  1075.         case 2:
  1076.             worm[2].deltax = 0;
  1077.             worm[2].deltay = -1;
  1078.         break;
  1079.         case 3:
  1080.             worm[3].deltax = 0;
  1081.             worm[3].deltay = 1;
  1082.         break;
  1083.         default:
  1084.         break;
  1085.             }   }
  1086.             turborender();
  1087.             delay = atleast(DELAY_MAX - (level * DELAY_DEC), DELAY_MIN);
  1088.  
  1089.             if (level)
  1090.             {   secondsperlevel = SECONDSPERLEVEL;
  1091.                 putletter(-1);
  1092.                 freq = (SBYTE) atleast(FREQ_MAX - (level * FREQ_DEC), FREQ_MIN);
  1093.                 for (i = 0; i <= 3; i++)
  1094.                 {   if (!worm[i].lives && worm[i].control != NONE)
  1095.                     {   /* create (or resurrect) a worm */
  1096.  
  1097.                         worm[i].lives      = STARTLIVES;
  1098.                         worm[i].score      = 0;
  1099.                         worm[i].oldscore   = 0;
  1100.                         worm[i].armour     = 0;
  1101.                         worm[i].tongue     = 0;
  1102.                         worm[i].alive      = TRUE;
  1103.                         worm[i].nitro      = FALSE;
  1104.                         worm[i].flashed    = FALSE;
  1105.                         worm[i].mode       = NOMODE;
  1106.                         worm[i].power      = 0;
  1107.                         worm[i].bias       = 0;
  1108.                         worm[i].multi      = 1;
  1109.                         worm[i].ice        = 0;
  1110.                         worm[i].victor     = -1;
  1111.                         worm[i].ammo       = 0;
  1112.                         worm[i].remnants   = FALSE;
  1113.                         worm[i].affixer    = FALSE;
  1114.                         worm[i].sideshot   = FALSE;
  1115.                         worm[i].pusher     = FALSE;
  1116.                         worm[i].rammed     = FALSE;
  1117.                         worm[i].freedom    = 0;
  1118.                         worm[i].causewait  = (ULONG) -1;
  1119.                         worm[i].last       = FIRSTTAIL + i;
  1120.                         worm[i].pos        = -1;
  1121.                         worm[i].cutter     = 0;
  1122.                         for (j = 0; j <= PROTECTORS; j++)
  1123.                             protector[i][j].alive = FALSE;
  1124.                         for (j = 0; j <= LASTOBJECT; j++)
  1125.                             stat(i, j);
  1126.                         icon(i, ICE);
  1127.                         icon(i, REMNANTS);
  1128.                         icon(i, AFFIXER);
  1129.                         icon(i, SIDESHOT);
  1130.                         icon(i, PUSHER);
  1131.                         icon(i, FREEDOM);
  1132.                         icon(i, CUTTER);
  1133.     }   }   }   }   }
  1134.     clearjoystick();
  1135.     clearkybd();
  1136.     resettime();
  1137. }
  1138.  
  1139. MODULE void explosion(SBYTE x, SBYTE y, SBYTE exceptionx, SBYTE exceptiony)
  1140. {   UBYTE i, generated = 0;
  1141.  
  1142. /* You wouldn't think this would work properly for pulse-explosions,
  1143. because the worm's head is obliterated. However, it is refreshed (as
  1144. tail) the next time wormloop() is called for that worm. */
  1145.  
  1146.     effect(FXGET_PULSE);
  1147.     for (i = 0; i <= CREATURES; i++)
  1148.     {   if ((!(creature[i].alive)) && generated <= 7)
  1149.         {   creature[i].last      = EMPTY;
  1150.             creature[i].x         = x;
  1151.             creature[i].y         = y;
  1152.             if (level)
  1153.                 creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1154.             else creature[i].speed = BONUSFRAGSPEED;
  1155.         creature[i].species   = FRAGMENT;
  1156.             creature[i].visible   = TRUE;
  1157.             switch (generated)
  1158.             {
  1159.             case 0:
  1160.                 creature[i].deltax = 0;
  1161.                 creature[i].deltay = -1;
  1162.             break;
  1163.             case 1:
  1164.                 creature[i].deltax = 1;
  1165.                 creature[i].deltay = -1;
  1166.             break;
  1167.             case 2:
  1168.                 creature[i].deltax = 1;
  1169.                 creature[i].deltay = 0;
  1170.             break;
  1171.             case 3:
  1172.                 creature[i].deltax = 1;
  1173.                 creature[i].deltay = 1;
  1174.             break;
  1175.             case 4:
  1176.                 creature[i].deltax = 0;
  1177.                 creature[i].deltay = 1;
  1178.             break;
  1179.             case 5:
  1180.                 creature[i].deltax = -1;
  1181.                 creature[i].deltay = 1;
  1182.             break;
  1183.             case 6:
  1184.                 creature[i].deltax = -1;
  1185.                 creature[i].deltay = 0;
  1186.             break;
  1187.             case 7:
  1188.                 creature[i].deltax = -1;
  1189.                 creature[i].deltay = -1;
  1190.             break;
  1191.             default:
  1192.             break;
  1193.             }
  1194.             generated++;
  1195.             if (creature[i].deltax != exceptionx || creature[i].deltay != exceptiony)
  1196.             {   creature[i].alive = TRUE;
  1197.                 if (generated == 1)
  1198.                     change(x, y, FRAGMENT);
  1199. }   }   }   }
  1200.  
  1201. /* Many creatures take advantage of shared characteristics.
  1202. 10 creature types (orbs, goats, drips, fragments, missiles, penguins,
  1203. cyclones, dogs, clouds, timebombs) use the creature structure.
  1204. Independent of it are worms, protectors, worm bullets and teleports. */
  1205.  
  1206. MODULE void creatureloop(SBYTE which)
  1207. {   ABOOL   happy = FALSE;
  1208.     UBYTE   bestdistance = 255, distance, player, c, i;
  1209.     SBYTE   x, y, xx, yy, xxx, yyy, frontx, fronty, rearx, reary;
  1210.  
  1211.     x = creature[which].x;
  1212.     y = creature[which].y;
  1213.  
  1214.     if (!valid(x, y)) // defensive programming
  1215.     {   creature[which].alive = FALSE;
  1216.         return;
  1217.  
  1218.         /* TEXT temp1[SAYLIMIT + 1], temp2[8];
  1219.  
  1220.         strcpy(temp1, "BAD CREATURE AT x: ");
  1221.         stci_d(temp2, x);
  1222.         strcat(temp1, temp2);
  1223.         strcat(temp1, ", y: ");
  1224.         stci_d(temp2, y);
  1225.         strcat(temp1, temp2);
  1226.         strcat(temp1, "!");
  1227.         say(temp1, PURPLE);
  1228.         draw(FIELDX + 1, 0, creature[which].species); // indicates which creature
  1229.         Delay(250);
  1230.         clearkybd();
  1231.         anykey(FALSE); */
  1232.     }
  1233.  
  1234.     if (creature[which].species == ORB && creature[which].explode)
  1235.     {   creature[which].alive = FALSE;
  1236.         explosion(x, y, -2, -2);
  1237.         return;
  1238.     }
  1239.  
  1240. /* decide whether and where to move */
  1241.  
  1242. switch(creature[which].species)
  1243. {
  1244. case CLOUD:
  1245.         if (creature[which].x == 0 || creature[which].x == FIELDX)
  1246.             creature[which].deltax = -creature[which].deltax;
  1247. break;
  1248. case TIMEBOMB:
  1249.     /* decrement and explode timebombs */
  1250.         if (field[x][y] != TIMEBOMB)
  1251.             creature[which].alive = FALSE;
  1252.         else
  1253.         {   effect(FXDO_BOMB);
  1254.             creature[which].time--;
  1255.             if (creature[which].time < 0)
  1256.             {   creature[which].alive = FALSE;
  1257.                 bombblast(BOMB, 0, x, y);
  1258.                 change(x, y, EMPTY);
  1259.             } else draw(x, y, ZERO + creature[which].time);
  1260.         }
  1261.         return; // not a bug
  1262. break;
  1263. case DOG:
  1264.         /* remove a movement from the dog queue */
  1265.  
  1266.         if (creature[which].dormant == CHASING)
  1267.         {   if (creature[which].pos != -1)
  1268.             {   creature[which].deltax = thedogqueue[which][0].deltax;
  1269.                 creature[which].deltay = thedogqueue[which][0].deltay;
  1270.                 if (--creature[which].pos != -1)
  1271.                 {   for (i = 0; i <= creature[which].pos; i++)
  1272.                     {   thedogqueue[which][i].deltax = thedogqueue[which][i + 1].deltax;
  1273.                         thedogqueue[which][i].deltay = thedogqueue[which][i + 1].deltay;
  1274.             }   }   }
  1275.             else creature[which].alive = FALSE;
  1276.         }
  1277. break;
  1278. case PENGUIN:
  1279.     do
  1280.     {    xx = (rand() % 3) - 1;
  1281.         yy = (rand() % 3) - 1;
  1282.     } while (!valid(x + xx, y + yy));
  1283.         c = field[x + xx][y + yy];
  1284.         if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1285.     {    creature[which].deltax = xx;
  1286.         creature[which].deltay = yy;
  1287.     } else
  1288.     {    creature[which].deltax = 0;
  1289.         creature[which].deltay = 0;
  1290.     }
  1291. break;
  1292. case WHIRLWIND:
  1293.     /* Whirlwinds has a slight upwards drift.
  1294.     Higher values of UNDRIFT make it less buoyant. */
  1295.  
  1296.     creature[which].deltax = (rand() % 3) - 1;
  1297.     if (!(rand() % UNDRIFT))
  1298.         creature[which].deltay = (rand() % 2) - 1;
  1299.     else creature[which].deltay = (rand() % 3) - 1;
  1300. break;
  1301. case MISSILE:
  1302.     for (player = 0; player <= 3; player++)
  1303.     {   if (creature[which].type != player && worm[player].lives && (!worm[player].bias))
  1304.         {   xx = abs(worm[player].x - x);
  1305.             yy = abs(worm[player].y - y);
  1306.             if (xx < yy)
  1307.                 distance = xx;
  1308.             else distance = yy;
  1309.             if (distance <= bestdistance)
  1310.             {   bestdistance = distance;
  1311.                 creature[which].deltax = bsign(worm[player].x - x);
  1312.                 creature[which].deltay = bsign(worm[player].y - y);
  1313.         }   }
  1314.     for (i = 0; i <= CREATURES; i++)
  1315.             if (creature[i].alive && which != i)
  1316.             {   if
  1317.                 (   creature[i].species == ORB
  1318.                 ||  (creature[i].species == MISSILE && creature[i].type != creature[which].type)
  1319.                 ||  creature[i].species == GOAT
  1320.                 )
  1321.                 {   xx = abs(creature[i].x - x);
  1322.                     yy = abs(creature[i].y - y);
  1323.                     if (xx < yy)
  1324.                         distance = xx;
  1325.                     else distance = yy;
  1326.                     if (distance <= bestdistance)
  1327.                     {   bestdistance = distance;
  1328.                         creature[which].deltax = bsign(creature[i].x - x);
  1329.                         creature[which].deltay = bsign(creature[i].y - y);
  1330.     }       }   }   }
  1331.     if (bestdistance == 255)
  1332.         creature[which].alive = FALSE;
  1333. break;
  1334. case ORB:
  1335.     frontx  = xwrap(x + creature[which].deltax);  /* look in front */
  1336.     fronty  = ywrap(y + creature[which].deltay);
  1337.     rearx   = xwrap(x - creature[which].deltax);  /* look behind */
  1338.     reary   = ywrap(y - creature[which].deltay);
  1339.     if (bounceorb(which, frontx, fronty))
  1340.     {   bouncegoat(which, frontx, fronty);
  1341.         xx = -creature[which].deltax; /* default bounce angle is 180° */
  1342.         yy = -creature[which].deltay;
  1343.         if (!bounceorb(which, frontx, reary))
  1344.         {    if (bounceorb(which, rearx, fronty))
  1345.             {   bouncegoat(which, rearx, fronty);
  1346.                 xx = creature[which].deltax;
  1347.         }    }
  1348.         elif (!bounceorb(which, rearx, fronty))
  1349.         {   bouncegoat(which, rearx, fronty);
  1350.             yy = creature[which].deltay;
  1351.         }
  1352.         creature[which].deltax = xx;
  1353.         creature[which].deltay = yy;
  1354.     }
  1355. break;
  1356. case GOAT:
  1357.     /* decide whether to move */
  1358.     if (!(rand() % GOATMOVE))
  1359.     {   for (xx = x - 1; xx <= x + 1; xx++)
  1360.             for (yy = y - 1; yy <= y + 1; yy++)
  1361.                 if (valid(xx, yy) && field[xx][yy] >= FIRSTEMPTY && field[xx][yy] <= LASTEMPTY)
  1362.                 {   happy = TRUE;
  1363.                     break;
  1364.     }            }
  1365.     creature[which].deltax = 0;
  1366.     creature[which].deltay = 0;
  1367.     if (!happy)
  1368.     {    xx = (rand() % 3) - 1;
  1369.         yy = (rand() % 3) - 1;
  1370.         if (valid(x + xx, y + yy) && (xx || yy))
  1371.                 {       c = field[x + xx][y + yy];
  1372.             if (c >= FIRSTGOAT && c <= LASTGOAT && c != GOAT)
  1373.             {    creature[which].last = creature[which].oldlast;
  1374.                                 creature[which].oldlast = c;
  1375.                 creature[which].deltax = xx;
  1376.                 creature[which].deltay = yy;
  1377.     }    }    }
  1378. break;
  1379. default:
  1380. break;
  1381. }
  1382.  
  1383. /* now move */
  1384.  
  1385. if (creature[which].deltax || creature[which].deltay)
  1386. {    if (creature[which].visible)
  1387.     {   /* erase previous image */
  1388.         change(x, y, creature[which].last);
  1389.             creature[which].last = EMPTY;
  1390.     }
  1391.     if (creature[which].alive)
  1392.     {   creature[which].x += creature[which].deltax;
  1393.         creature[which].y += creature[which].deltay;
  1394.         if (creature[which].species == ORB)
  1395.         {   creature[which].x = xwrap(creature[which].x);
  1396.             creature[which].y = ywrap(creature[which].y);
  1397.         } elif (creature[which].species == FRAGMENT || creature[which].species == DRIP || creature[which].species == WHIRLWIND || creature[which].species == DOG)
  1398.         {    if (!valid(creature[which].x, creature[which].y))
  1399.                 creature[which].alive = FALSE;
  1400. }    }   }
  1401.  
  1402. creature[which].visible = TRUE;
  1403. x = creature[which].x;
  1404. y = creature[which].y;
  1405.  
  1406. /* Collision detection.
  1407. Goats, penguins, timebombs don't need to go through this. */
  1408.  
  1409. if
  1410. (    creature[which].alive
  1411. &&    creature[which].species != GOAT
  1412. &&    creature[which].species != PENGUIN
  1413. &&    (creature[which].deltax || creature[which].deltay)
  1414. )
  1415. {       c = field[x][y];
  1416.  
  1417.     if (c >= FIRSTHEAD && c <= LASTHEAD)
  1418.     {   if (creature[which].species == MISSILE)
  1419.             wormmissile(x, y, c - FIRSTHEAD, which);
  1420.         elif (creature[which].species == DOG)
  1421.             wormdog(x, y, c - FIRSTHEAD, which);
  1422.         elif (creature[which].species == FRAGMENT)
  1423.             wormfrag(x, y, c - FIRSTHEAD, which);
  1424.         elif (creature[which].species == DRIP)
  1425.             wormdrip(x, y, c - FIRSTHEAD, which);
  1426.         elif (creature[which].species == WHIRLWIND)
  1427.             wormwhirlwind(x, y, c - FIRSTHEAD, which);
  1428.         elif (creature[which].species == CLOUD)
  1429.             cloudworm(x, y, which, c - FIRSTHEAD);
  1430.         elif (creature[which].species == ORB)
  1431.         {   wormorb(x, y, c - FIRSTHEAD, which);
  1432.             creature[which].last = c - FIRSTHEAD + FIRSTTAIL; /* note sign issues */
  1433.     }   }
  1434.     elif (c == TIMEBOMB)
  1435.     {   creature[whichcreature(x, y, TIMEBOMB, which)].alive = FALSE;
  1436.         bombblast(BOMB, 0, x, y);
  1437.         change(x, y, EMPTY);
  1438.     } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1439.     {   if (creature[which].species == ORB)
  1440.         {   if (creature[which].mode == TONGUE)
  1441.                 effect(FXUSE_TONGUE);
  1442.             else
  1443.             {   if (worm[c - FIRSTTAIL].alive)
  1444.                 {   effect(FXDEATH_ORB);
  1445.                     wormscore(c - FIRSTTAIL, creature[which].score);
  1446.                     if (worm[c - FIRSTTAIL].bias)
  1447.                     {   worm[c - FIRSTTAIL].lives += ORBBLOOD;
  1448.                         stat(c - FIRSTTAIL, LIFE);
  1449.                 }   }
  1450.                 creature[which].alive = FALSE;
  1451.                 change(x, y, BONUS);
  1452.     }   }   }
  1453.     elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  1454.     {   if (creature[which].species == DOG)
  1455.             protdog(x, y, c - FIRSTPROTECTOR, which);
  1456.         elif (creature[which].species == DRIP)
  1457.             protdrip(x, y, c - FIRSTPROTECTOR, which);
  1458.         elif (creature[which].species == MISSILE)
  1459.             protmissile(x, y, c - FIRSTPROTECTOR, which);
  1460.         elif (creature[which].species == FRAGMENT)
  1461.             protfrag(x, y, c - FIRSTPROTECTOR, which);
  1462.         elif (creature[which].species == ORB)
  1463.             protorb(x, y, c - FIRSTPROTECTOR, which);
  1464.         elif (creature[which].species == PENGUIN)
  1465.             protpenguin(x, y, c - FIRSTPROTECTOR, which);
  1466.         elif (creature[which].species == WHIRLWIND)
  1467.             protwhirlwind(x, y, c - FIRSTPROTECTOR, which);
  1468.         elif (creature[which].species == CLOUD)
  1469.             cloudprot(x, y, which, c - FIRSTPROTECTOR);
  1470.     } elif (c >= FIRSTLETTER && c <= LASTLETTER)
  1471.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1472.         {   effect(FXDEATH_FRAGMENT);
  1473.             creature[which].alive = FALSE;
  1474.         } elif (creature[which].species == ORB)
  1475.         {   for (player = 0; player <= 3; player++)
  1476.             {   letters[player][c - FIRSTLETTER] = FALSE;
  1477.                 drawletter(player, c, BLACK);
  1478.             }
  1479.             putletter(-1);
  1480.             orbscore(which, LETTERPOINT);
  1481.         } elif (creature[which].species == WHIRLWIND)
  1482.             putletter(-1);
  1483.     } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  1484.     {   i = whichcreature(x, y, DRIP, which);
  1485.         if (creature[which].species == FRAGMENT)
  1486.             dripfrag(x, y, i, which);
  1487.         elif (creature[which].species == MISSILE)
  1488.             dripmissile(x, y, i, which);
  1489.         elif (creature[which].species == ORB)
  1490.             driporb(x, y, i, which);
  1491.         elif (creature[which].species == WHIRLWIND)
  1492.             dripwhirlwind(x, y, i, which);
  1493.         elif (creature[which].species == CLOUD)
  1494.             clouddrip(x, y, which, i);
  1495.     } elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  1496.     {   i = whichcreature(x, y, MISSILE, which);
  1497.         if (creature[which].species == FRAGMENT)
  1498.             fragmissile(x, y, which, i);
  1499.         elif (creature[which].species == DRIP)
  1500.             dripmissile(x, y, which, i);
  1501.         elif (creature[which].species == ORB)
  1502.             orbmissile(x, y, which, i);
  1503.         elif (creature[which].species == WHIRLWIND)
  1504.             missilewhirlwind(x, y, i, which);
  1505.         elif (creature[which].species == MISSILE)
  1506.             missilemissile(x, y, which, i);
  1507.         elif (creature[which].species == CLOUD)
  1508.             cloudmissile(x, y, which, i);
  1509.     } elif (c == WHIRLWIND)
  1510.     {   i = whichcreature(x, y, WHIRLWIND, which);
  1511.         if (creature[which].species == DRIP)
  1512.             dripwhirlwind(x, y, which, i);
  1513.         elif (creature[which].species == MISSILE)
  1514.             missilewhirlwind(x, y, which, i);
  1515.         elif (creature[which].species == ORB)
  1516.             orbwhirlwind(x, y, which, i);
  1517.         elif (creature[which].species == WHIRLWIND)
  1518.             whirlwindwhirlwind(x, y, which, i);
  1519.         elif (creature[which].species == FRAGMENT)
  1520.             fragwhirlwind(x, y, which, i);
  1521.         elif (creature[which].species == CLOUD)
  1522.             cloudwhirlwind(x, y, which, i);
  1523.     } elif (c == DOG)
  1524.     {   i = whichcreature(x, y, DOG, which);
  1525.         if (creature[which].species == FRAGMENT)
  1526.             dogfrag(x, y, i, which);
  1527.         elif (creature[which].species == PENGUIN)
  1528.             dogpenguin(x, y, i, which);
  1529.         elif (creature[which].species == ORB)
  1530.             dogorb(x, y, i, which);
  1531.         elif (creature[i].species == DRIP)
  1532.             dogdrip(x, y, i, which);
  1533.         elif (creature[i].species == WHIRLWIND)
  1534.             dogwhirlwind(x, y, i, which);
  1535.         elif (creature[i].species == MISSILE)
  1536.             dogmissile(x, y, i, which);
  1537.         elif (creature[i].species == DOG)
  1538.             dogdog(x, y, i, which);
  1539.         elif (creature[i].species == CLOUD)
  1540.             clouddog(x, y, which, i);
  1541.     } elif (c == PENGUIN)
  1542.     {   i = whichcreature(x, y, PENGUIN, which);
  1543.         if (creature[which].species == ORB)
  1544.             orbpenguin(x, y, which, i);
  1545.         elif (creature[which].species == DOG)
  1546.             dogpenguin(x, y, which, i);
  1547.         elif (creature[which].species == WHIRLWIND)
  1548.             penguinwhirlwind(x, y, i, which);
  1549.         elif (creature[which].species == MISSILE)
  1550.             missilepenguin(x, y, which, i);
  1551.         elif (creature[which].species == DRIP)
  1552.             drippenguin(x, y, which, i);
  1553.         elif (creature[which].species == CLOUD)
  1554.             cloudpenguin(x, y, which, i);
  1555.     } elif (c == FRAGMENT)
  1556.     {   i = whichcreature(x, y, FRAGMENT, which);
  1557.         if (creature[which].species == MISSILE)
  1558.             fragmissile(x, y, i, which);
  1559.         elif (creature[which].species == DRIP)
  1560.             dripfrag(x, y, which, i);
  1561.         elif (creature[which].species == ORB)
  1562.             fragorb(x, y, i, which);
  1563.         elif (creature[which].species == FRAGMENT)
  1564.             fragfrag(x, y, which, i);
  1565.         elif (creature[which].species == WHIRLWIND)
  1566.             fragwhirlwind(x, y, i, which);
  1567.         elif (creature[which].species == CLOUD)
  1568.             cloudfrag(x, y, which, i);
  1569.         elif (creature[which].species == DOG)
  1570.             dogfrag(x, y, which, i);
  1571.     } elif (c == METAL)
  1572.     {   if (creature[which].species == DRIP || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1573.             creature[which].alive = FALSE;
  1574.         elif (creature[which].species == FRAGMENT)
  1575.             reflect(which);
  1576.     } elif (c == STONE)
  1577.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1578.         {   effect(FXDEATH_FRAGMENT);
  1579.             creature[which].alive = FALSE;
  1580.     }   }
  1581.     elif (c == WOOD)
  1582.     {   if (creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD || creature[which].species == DRIP)
  1583.         {   effect(FXDEATH_FRAGMENT);
  1584.             creature[which].alive = FALSE;
  1585.     }   }
  1586.     elif (c == GOAT)
  1587.     {   /* Drips, fragments, missiles, cyclones, dogs, clouds */
  1588.         creature[whichcreature(x, y, GOAT, which)].alive = FALSE;
  1589.         effect(FXDEATH_GOAT);
  1590.         if (creature[which].species != WHIRLWIND)
  1591.         {   creature[which].alive = FALSE;
  1592.             change(x, y, BONUS);
  1593.         }
  1594.         if (creature[which].species == MISSILE)
  1595.         {   wormscore(creature[which].type, KILLGOAT);
  1596.             if (worm[creature[which].type].bias)
  1597.             {   worm[creature[which].type].lives += GOATBLOOD;
  1598.                 stat(creature[which].type, LIFE);
  1599.     }   }   }
  1600.     elif (c == SLIME)
  1601.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || (creature[which].species == ORB && creature[which].mode != ARMOUR))
  1602.         {   creature[which].alive = FALSE;
  1603.             change(x, y, EMPTY);
  1604.     }   }
  1605.     elif (c == SKULL)
  1606.     {   if (creature[which].species == ORB)
  1607.         {   effect(FXGET_SKULL);
  1608.             orbscore(which, SKULLPOINT);
  1609.         } elif (creature[which].species == FRAGMENT || creature[which].species == DRIP || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1610.         {   effect(FXDEATH_FRAGMENT);
  1611.             creature[which].alive = FALSE;
  1612.     }   }
  1613.     elif (c == TELEPORT)
  1614.     {   /* Drips, fragments, missiles, orbs, whirlwinds, dogs, clouds */
  1615.         i = whichteleport(x, y);
  1616.         if (blocked(i, creature[which].deltax, creature[which].deltay))
  1617.             creature[which].alive = FALSE;
  1618.         else
  1619.         {   effect(FXUSE_TELEPORT);
  1620.             creature[which].x = teleport[level][partner(i)].x + creature[which].deltax;
  1621.             creature[which].y = teleport[level][partner(i)].y + creature[which].deltay;
  1622.  
  1623.             if (creature[which].species == ORB)
  1624.             {   orbscore(which, TELPOINT);
  1625.                 creature[which].x = xwrap(creature[which].x);
  1626.                 creature[which].y = ywrap(creature[which].y);
  1627.             } else
  1628.             {   if (!(valid(creature[which].x, creature[which].y)))
  1629.                     creature[which].alive = FALSE;
  1630.                 if (creature[which].species == FRAGMENT)
  1631.                     creature[which].last = SILVER;
  1632.     }   }   }
  1633.     elif (c == ORB)
  1634.     {   i = whichcreature(x, y, ORB, which);
  1635.         if (creature[which].species == DRIP)
  1636.             driporb(x, y, which, i);
  1637.         elif (creature[which].species == FRAGMENT)
  1638.             fragorb(x, y, which, i);
  1639.         elif (creature[which].species == WHIRLWIND)
  1640.             orbwhirlwind(x, y, i, which);
  1641.         elif (creature[which].species == PENGUIN)
  1642.             orbpenguin(x, y, i, which);
  1643.         elif (creature[which].species == MISSILE)
  1644.             orbmissile(x, y, i, which);
  1645.         elif (creature[which].species == DOG)
  1646.             dogorb(x, y, which, i);
  1647.         elif (creature[which].species == ORB)
  1648.             orborb(x, y, which, i);
  1649.         elif (creature[which].species == CLOUD)
  1650.             cloudorb(x, y, which, i);
  1651.     } elif (c == CLOUD)
  1652.     {   i = whichcreature(x, y, CLOUD, which);
  1653.         if (creature[which].species == DRIP)
  1654.             clouddrip(x, y, which, i);
  1655.         elif (creature[which].species == FRAGMENT)
  1656.             cloudfrag(x, y, which, i);
  1657.         elif (creature[which].species == WHIRLWIND)
  1658.             cloudwhirlwind(x, y, which, i);
  1659.         elif (creature[which].species == PENGUIN)
  1660.             cloudpenguin(x, y, which, i);
  1661.         elif (creature[which].species == MISSILE)
  1662.             cloudmissile(x, y, which, i);
  1663.         elif (creature[which].species == DOG)
  1664.             clouddog(x, y, which, i);
  1665.         elif (creature[which].species == ORB)
  1666.             cloudorb(x, y, which, i);
  1667.         elif (creature[which].species == CLOUD)
  1668.             cloudcloud(x, y, which, i);
  1669.     } elif (creature[which].species == ORB)
  1670.     {   if (c <= LASTOBJECT)
  1671.         {   orbscore(which, object[c].score);
  1672.             if (c == AMMO || c == PULSE || c == SLAYER || c == LIGHTNING)
  1673.             {   if (creature[which].mode != ARMOUR)
  1674.                     creature[which].explode = TRUE;
  1675.                 else effect(FXUSE_ARMOUR);
  1676.             } elif (c == NITRO || c == POWER || c == SLOWER || c == CYCLONE)
  1677.             {   effect(FXGET_NITRO);
  1678.                 creature[which].speed = speedup(creature[which].speed, TRUE);
  1679.             } elif (c == HEALER || c == LIFE || c == ICE || c == TREASURE || c == UMBRELLA || c == BONUS)
  1680.                 orbsplit(which);
  1681.             else switch (c)
  1682.             {
  1683.             case BOMB:
  1684.                 draw(x, y, ORB);
  1685.                 bombblast(ORB, which, x, y);
  1686.             break;
  1687.             case ARMOUR:
  1688.                 creature[which].armour += MODEADD + (rand() % MODERAND);
  1689.                 creature[which].mode = ARMOUR;
  1690.             break;
  1691.             case TONGUE:
  1692.                 creature[which].tongue += MODEADD + (rand() % MODERAND);
  1693.                 creature[which].mode = TONGUE;
  1694.             break;
  1695.             case PROTECTOR:
  1696.                 for (player = 0; player <= 3; player++)
  1697.                     if (worm[player].lives)
  1698.                         for (i = 0; i <= PROTECTORS; i++)
  1699.                            if (protector[player][i].alive)
  1700.                            {   protector[player][i].alive = FALSE;
  1701.                                if (protector[player][i].visible)
  1702.                                    change(protector[player][i].x, protector[player][i].y, EMPTY);
  1703.                            }
  1704.             break;
  1705.             case MISSILE:
  1706.             case CONVERTER:
  1707.                 effect(FXGET_OBJECT);
  1708.                 for (i = 0; i <= CREATURES; i++)
  1709.                 {   if (creature[i].alive && creature[i].species == MISSILE)
  1710.                     {   creature[i].alive = FALSE;
  1711.                         change(x, y, EMPTY);
  1712.                 }   }
  1713.             break;
  1714.             case MULTIPLIER:
  1715.                 effect(FXGET_OBJECT);
  1716.                 creature[which].multi *= 2;
  1717.                 if (creature[which].multi > MULTILIMIT)
  1718.                     creature[which].multi = MULTILIMIT;
  1719.             break;
  1720.             case BIAS:
  1721.                 effect(FXGET_OBJECT);
  1722.                 for (player = 0; player <= 3; player++)
  1723.                     if (worm[player].lives && worm[player].bias)
  1724.                     {   worm[player].bias = 0;
  1725.                         stat(player, BIAS);
  1726.                     }
  1727.             break;
  1728.             case AFFIXER:
  1729.                 effect(FXGET_OBJECT);
  1730.                 for (player = 0; player <= 3; player++)
  1731.                     if (worm[player].lives)
  1732.                     {   worm[player].affixer = FALSE;
  1733.                         icon(player, AFFIXER);
  1734.                     }
  1735.             break;
  1736.             case REMNANTS:
  1737.                 effect(FXGET_OBJECT);
  1738.                 for (player = 0; player <= 3; player++)
  1739.                     if (worm[player].lives)
  1740.                     {   worm[player].remnants = FALSE;
  1741.                         icon(player, REMNANTS);
  1742.                     }
  1743.             break;
  1744.             case SIDESHOT:
  1745.                 effect(FXGET_POWERUP);
  1746.                 for (player = 0; player <= 3; player++)
  1747.                     if (worm[player].lives)
  1748.                     {   worm[player].sideshot = FALSE;
  1749.                         icon(player, SIDESHOT);
  1750.                     }
  1751.             break;
  1752.             case MAGNET:
  1753.                 effect(FXGET_OBJECT);
  1754.                 for (i = 0; i <= MAGNETS; i++)
  1755.                     if (magnet[i].alive)
  1756.                         magnet[i].alive = FALSE;
  1757.             break;
  1758.             case PUSHER:
  1759.                 effect(FXGET_OBJECT);
  1760.                 for (i = 0; i <= 3; i++)
  1761.                     if (worm[i].lives && worm[i].pusher)
  1762.                     {   worm[i].pusher = FALSE;
  1763.                         icon(player, PUSHER);
  1764.                     }
  1765.             break;
  1766.             case FREEDOM:
  1767.                 effect(FXGET_OBJECT);
  1768.                 for (xx = 0; xx <= FIELDX; xx++)
  1769.                     for (yy = 0; yy <= FIELDY; yy++)
  1770.                         if (field[xx][yy] >= FIRSTFIRE && field[xx][yy] <= LASTFIRE)
  1771.                             change(xx, yy, EMPTY);
  1772.             break;
  1773.             case SWITCHER:
  1774.                 effect(FXGET_OBJECT);
  1775.                 for (xx = 0; xx <= FIELDX; xx++)
  1776.                     for (yy = 0; yy <= FIELDY; yy++)
  1777.                         if (field[xx][yy] >= FIRSTTAIL && field[xx][yy] <= LASTTAIL)
  1778.                             change(xx, yy, WOOD);
  1779.             break;
  1780.             case GROWER:
  1781.                 effect(FXGET_GROWER);
  1782.                 for (xx = 0; xx <= FIELDX; xx++)
  1783.                     for (yy = 0; yy <= FIELDY; yy++)
  1784.                         if (field[xx][yy] == WOOD)
  1785.                             for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  1786.                                 for (yyy = yy - 1; yyy <= yy + 1; yyy++)                                                                if (valid(xxx, yyy) && field[xxx][yyy] == EMPTY)
  1787.                                     field[xxx][yyy] = TEMPWOOD;
  1788.                 for (xx = 0; xx <= FIELDX; xx++)
  1789.                     for (yy = 0; yy <= FIELDY; yy++)
  1790.                         if (field[xx][yy] == TEMPWOOD)
  1791.                             change(xx, yy, WOOD);
  1792.             break;
  1793.             case CLOCK:
  1794.                 secondsperlevel -= rand() % CLOCKRAND;
  1795.                 if (secondsperlevel < 0)
  1796.                     secondsperlevel = 0;
  1797.             break;
  1798.             case CUTTER:
  1799.                 for (i = 0; i <= 3; i++)
  1800.                     if (worm[i].lives && worm[i].cutter)
  1801.                     {   worm[i].cutter = 0;
  1802.                         icon(player, CUTTER);
  1803.                     }
  1804.             break;
  1805.             default:
  1806.                 // assert(0);
  1807.             break;
  1808.         }   }
  1809.         elif (c == EMPTY)
  1810.             orbscore(which, EMPTYPOINT);
  1811.         elif (c == SILVER)
  1812.             orbscore(which, SILVERPOINT);
  1813.         elif (c == GOLD)
  1814.             orbscore(which, GOLDPOINT);
  1815. }   }
  1816.  
  1817. x = creature[which].x; /* We refresh these in case a fragment has been */
  1818. y = creature[which].y; /* reflected. Yes, it is vital. */
  1819.  
  1820. if (creature[which].alive && creature[which].visible && (creature[which].deltax || creature[which].deltay))
  1821. {   if (creature[which].species == MISSILE)
  1822.         change(x, y, FIRSTMISSILE + creature[which].type);
  1823.     elif (creature[which].species == DRIP)
  1824.         change(x, y, FIRSTDRIP + creature[which].type);
  1825.     elif (creature[which].species == ORB)
  1826.     {   field[x][y] = ORB;
  1827.         if (creature[which].mode == TONGUE)
  1828.             draw(x, y, ORBTONGUE);
  1829.         elif (creature[which].mode == ARMOUR)
  1830.             draw(x, y, ORBARMOUR);
  1831.         else draw(x, y, ORB);
  1832.     } else /* fragments, goats, penguins, cyclones, dogs, clouds */
  1833.     change(x, y, creature[which].species);
  1834. }
  1835.  
  1836. if (creature[which].alive)
  1837. {   /* decide whether to fire */
  1838.     if (creature[which].species == GOAT)
  1839.     {   if (!(rand() % 10))
  1840.         {   for (i = 0; i <= CREATURES; i++)
  1841.             {   if (!creature[i].alive)
  1842.                 {   creature[i].deltax = (rand() % 3) - 1;
  1843.                     creature[i].deltay = (rand() % 3) - 1;
  1844.                     if
  1845.                     (   valid(x + creature[i].deltax, y + creature[i].deltay)
  1846.                     &&  (creature[i].deltax || creature[i].deltay)
  1847.                     )
  1848.                     {   c = field[x + creature[i].deltax][y + creature[i].deltay];
  1849.                         if
  1850.                         (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1851.                         ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1852.                         )
  1853.                         {   effect(FXDO_GOAT);
  1854.                             creature[i].alive = TRUE;
  1855.                             creature[i].species = FRAGMENT;
  1856.                             creature[i].x = x + creature[i].deltax;
  1857.                             creature[i].y = y + creature[i].deltay;
  1858.                             creature[i].visible = TRUE;
  1859.                             creature[i].last = EMPTY;
  1860.                             creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1861.                     }   }
  1862.                     break;
  1863.     }   }   }   }
  1864.     elif (creature[which].species == CLOUD)
  1865.     {   if (!(rand() % 30))
  1866.         {   cloudbullet(which, x, y, -1);
  1867.             cloudbullet(which, x, y, 1);
  1868. }   }   }
  1869. }
  1870.  
  1871. MODULE void cloudbullet(UBYTE which, SBYTE x, SBYTE y, SBYTE deltay)
  1872. {   UBYTE i, c;
  1873.  
  1874.     for (i = 0; i <= CREATURES; i++)
  1875.     {   if (!creature[i].alive)
  1876.         {   creature[i].deltax = 0;
  1877.             creature[i].deltay = deltay;
  1878.             if (valid(x + creature[i].deltax, y + creature[i].deltay))
  1879.             {   c = field[x + creature[i].deltax][y + creature[i].deltay];
  1880.                 if
  1881.                 (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1882.                 ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1883.                 )
  1884.                 {   effect(FXDO_CLOUD);
  1885.                     creature[i].alive = TRUE;
  1886.                     creature[i].species = FRAGMENT;
  1887.                     creature[i].x = x;
  1888.                     creature[i].y = y + creature[i].deltay;
  1889.                     creature[i].visible = TRUE;
  1890.                     creature[i].last = EMPTY;
  1891.                     creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1892.             }   }
  1893.             break;
  1894. }   }   }
  1895.  
  1896. MODULE void orbsplit(SBYTE which)
  1897. {   SBYTE   copy = 0, i;
  1898.  
  1899.     effect(FXDO_ORB);
  1900.     for (i = 0; i <= CREATURES; i++)
  1901.     {   if (!creature[i].alive)
  1902.         {   creature[i].x       = creature[which].x;
  1903.             creature[i].y       = creature[which].y;
  1904.             creature[i].score   = creature[which].score;
  1905.             creature[i].armour  = creature[which].armour;
  1906.             creature[i].tongue  = creature[which].tongue;
  1907.             creature[i].mode    = creature[which].mode;
  1908.             creature[i].speed   = creature[which].speed;
  1909.             creature[i].explode = FALSE;
  1910.             creature[i].multi   = creature[which].multi;
  1911.             creature[i].last    = EMPTY;
  1912.             creature[i].species = ORB;
  1913.             switch (copy)
  1914.             {
  1915.             case 0:
  1916.                 if (creature[which].deltax != -1 || creature[which].deltay != -1)
  1917.                 {   creature[i].deltax = -1;
  1918.                     creature[i].deltay = -1;
  1919.                     creature[i].alive = TRUE;
  1920.                 }
  1921.             break;
  1922.             case 1:
  1923.                 if (creature[which].deltax != 1 || creature[which].deltay != 1)
  1924.                 {   creature[i].deltax = 1;
  1925.                     creature[i].deltay = 1;
  1926.                     creature[i].alive = TRUE;
  1927.                 }
  1928.             break;
  1929.             case 2:
  1930.                 if (creature[which].deltax != 1 || creature[which].deltay != -1)
  1931.                 {   creature[i].deltax = 1;
  1932.                     creature[i].deltay = -1;
  1933.                     creature[i].alive = TRUE;
  1934.                 }
  1935.             break;
  1936.             case 3:
  1937.                 if (creature[which].deltax != -1 || creature[which].deltay != 1)
  1938.                 {   creature[i].deltax = -1;
  1939.                     creature[i].deltay = 1;
  1940.                     creature[i].alive = TRUE;
  1941.                 }
  1942.             break;
  1943.             default:
  1944.             break;
  1945.             }
  1946.             if (++copy >= 4)
  1947.                 return;
  1948. }   }   }
  1949.  
  1950. SBYTE partner(SBYTE which)
  1951. {   if (which % 2 == 0)
  1952.         return((SBYTE) (which + 1));
  1953.     else return((SBYTE) (which - 1));
  1954. }
  1955.  
  1956. /* NAME     putletter -- Put a letter onto the field
  1957. SYNOPSIS    void putletter(SBYTE player);
  1958. INPUTS      SBYTE player -
  1959.             0-3: player on whose behalf the letter is put on for
  1960.             -1: any letter
  1961. RESULT      none */
  1962.  
  1963. MODULE void putletter(SBYTE player)
  1964. {   ABOOL done;
  1965.     SBYTE i, x, y;
  1966.     UBYTE letter;
  1967.  
  1968.     do
  1969.     {   done = findempty(&x, &y, FIRSTEMPTY, LASTEMPTY);
  1970.     } while (!done);
  1971.     if (player != -1)
  1972.     {   for (i = 0; i <= LETTERS; i++)
  1973.             if (!(letters[player][i]))
  1974.             {   break;
  1975.             }
  1976.         if (i > LETTERS) /* if no spare letters */
  1977.             letter = rand() % (LETTERS + 1);
  1978.         else
  1979.         {   do
  1980.                 letter = rand() % (LETTERS + 1);
  1981.             while (letters[player][letter]);
  1982.     }   }
  1983.     else letter = rand() % (LETTERS + 1);
  1984.     change(x, y, letter + FIRSTLETTER);
  1985.  
  1986.     letterx = x;
  1987.     lettery = y;
  1988.     lettertype = letter + FIRSTLETTER;
  1989. }
  1990.  
  1991. /* NAME     queue -- adds a keystroke to the key queue
  1992. SYNOPSIS    name(SBYTE, SBYTE, SBYTE);
  1993. FUNCTION    Adds a keystroke to the in-game key queue.
  1994. INPUTS      player - player that pressed the key
  1995.             deltax - the deltax of the key
  1996.             deltay - the deltay of the key
  1997. IMPLEMENTATION
  1998.             thewormqueue[] array has WORMQUEUELIMIT as its last index.
  1999.             It is implemented as a FIFO stack rather than LIFO so that
  2000.             the keystrokes are processed in the correct order (that is,
  2001.             the order in which they were pressed). The oldest keystroke
  2002.             is always at index [0], the next oldest at [1], and so on
  2003.             upwards to the newest keystroke, at [worm[player].pos].
  2004.             Keystrokes are removed from the bottom of the array ([0]),
  2005.             and the rest of the array is shuffled down to fill the gap,
  2006.             so that the contents of [1] go to [0], the contents of [2]
  2007.             go to [1], etc. worm[player].pos is adjusted to always point
  2008.             to the newest entry, which is the 'end' of the queue.
  2009. MODULE      engine.c */
  2010.  
  2011. void wormqueue(SBYTE player, SBYTE deltax, SBYTE deltay)
  2012. {       if (worm[player].pos < WORMQUEUELIMIT)
  2013.     {    worm[player].pos++;
  2014.         thewormqueue[player][worm[player].pos].deltax = deltax;
  2015.         thewormqueue[player][worm[player].pos].deltay = deltay;
  2016. }    }
  2017.  
  2018. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay)
  2019. {   if (creature[which].pos < DOGQUEUELIMIT)
  2020.     {   creature[which].pos++;
  2021.         thedogqueue[which][creature[which].pos].deltax = deltax;
  2022.         thedogqueue[which][creature[which].pos].deltay = deltay;
  2023.     } else
  2024.     {   creature[which].alive = FALSE;
  2025.         change(creature[which].x, creature[which].y, EMPTY);
  2026. }   }
  2027.  
  2028. MODULE void reflect(UBYTE which)
  2029. {   creature[which].deltax  = -creature[which].deltax;
  2030.     creature[which].deltay  = -creature[which].deltay;
  2031.     creature[which].x      +=  creature[which].deltax * 2;
  2032.     creature[which].y      +=  creature[which].deltay * 2;
  2033. }
  2034.  
  2035. ABOOL savefields(STRPTR fieldname)
  2036. {   SBYTE i, j;
  2037.     TEXT  IOBuffer[NAMELENGTH + 1];
  2038.  
  2039.     matchteleports();
  2040.  
  2041.     if (!ZOpen(fieldname, TRUE))
  2042.         return FALSE;
  2043.  
  2044.     /* write header */
  2045.  
  2046.     strcpy(IOBuffer, "FSET 6.3");
  2047.     IOBuffer[9] = levels;
  2048.     if (!ZWrite(IOBuffer, 10))
  2049.     {   ZClose();
  2050.         return FALSE;
  2051.     }
  2052.  
  2053.     /* write high score table */
  2054.  
  2055.     for (i = 0; i <= HISCORES; i++)
  2056.     {   IOBuffer[0]                                             =  hiscore[i].player;
  2057.         IOBuffer[1]                                             =  hiscore[i].level;
  2058.  
  2059.         IOBuffer[2]                                             =   hiscore[i].score / 16777216;
  2060.         IOBuffer[3]                                             =  (hiscore[i].score % 16777216) / 65536;
  2061.         IOBuffer[4]                                             = ((hiscore[i].score % 16777216) % 65536) / 256;
  2062.         IOBuffer[5]                                             = ((hiscore[i].score % 16777216) % 65536) % 256;
  2063.         if (!ZWrite(IOBuffer, 6))
  2064.         {   ZClose();
  2065.             return FALSE;
  2066.         }
  2067.  
  2068.         for (j = 0; j <= NAMELENGTH; j++)
  2069.             IOBuffer[j]                                             = hiscore[i].name[j];
  2070.         if (!ZWrite(IOBuffer, NAMELENGTH + 1))
  2071.         {   ZClose();
  2072.             return FALSE;
  2073.         }
  2074.         for (j = 0; j <= TIMELENGTH; j++)
  2075.             IOBuffer[j]                                             = hiscore[i].time[j];
  2076.         if (!ZWrite(IOBuffer, TIMELENGTH + 1))
  2077.         {   ZClose();
  2078.             return FALSE;
  2079.         }
  2080.         for (j = 0; j <= DATELENGTH; j++)
  2081.             IOBuffer[j]                                             = hiscore[i].date[j];
  2082.         if (!ZWrite(IOBuffer, DATELENGTH + 1))
  2083.         {   ZClose();
  2084.             return FALSE;
  2085.     }   }
  2086.  
  2087.     /* write level data */
  2088.  
  2089.     for (i = 0; i <= levels; i++)
  2090.     {   IOBuffer[0]                        = startx[i];
  2091.         IOBuffer[1]                        = starty[i];
  2092.         IOBuffer[2]                                             = teleport[i][0].alive;
  2093.         IOBuffer[3]                                             = teleport[i][0].x;
  2094.         IOBuffer[4]                                             = teleport[i][0].y;
  2095.         IOBuffer[5]                                             = teleport[i][1].alive;
  2096.         IOBuffer[6]                                             = teleport[i][1].x;
  2097.         IOBuffer[7]                                             = teleport[i][1].y;
  2098.         if (!ZWrite(IOBuffer, 8))
  2099.         {   ZClose();
  2100.             return FALSE;
  2101.         }
  2102.  
  2103.         if (!ZWrite((char *) &board[i][0][0], (FIELDX + 1) * (FIELDY + 1)))
  2104.         {   ZClose();
  2105.             return FALSE;
  2106.     }   }
  2107.  
  2108.     /* write version string */
  2109.  
  2110.     if (!ZWrite(VERSION, strlen(VERSION)))
  2111.     {   ZClose();
  2112.         return FALSE;
  2113.     }
  2114.  
  2115.     ZClose();
  2116.  
  2117.     if (clearthem)
  2118.         clearhiscores();
  2119.     modified = FALSE;
  2120.     return TRUE;
  2121. }
  2122.  
  2123. void saylevel(COLOUR colour)
  2124. {    TEXT mainstring[15] = "Level ", tempstring[4];
  2125.  
  2126.     if (level > 0)
  2127.     {    stci_d(&mainstring[6], level);
  2128.         strcat((char*) mainstring, " of ");
  2129.         stci_d(tempstring, levels);
  2130.         strcat((char*) mainstring, (char*) tempstring);
  2131.         say(mainstring, colour);
  2132.     } else
  2133.     {    if (a == FIELDEDIT)
  2134.             say("Bonus Level", colour);
  2135.         else
  2136.         {    if (leveltype == TREASURE)
  2137.                             say("Bonus Level: Treasury!", colour);
  2138.                         elif (leveltype == DRIP)
  2139.                             say("Bonus Level: Drips!", colour);
  2140.                         else
  2141.                         {   // assert(leveltype == PENGUIN);
  2142.                             say("Bonus Level: Penguins!", colour);
  2143. }       }       }       }
  2144.  
  2145. MODULE SBYTE slowdown(SBYTE speed, ABOOL nitro)
  2146. {    speed *= 2;
  2147.         if (nitro)
  2148.         {   if (speed > VERYSLOW)
  2149.                 speed = VERYSLOW;
  2150.         } elif (speed > SLOW)
  2151.             speed = SLOW;
  2152.     return(speed);
  2153. }
  2154.  
  2155. MODULE void slowloop(void)
  2156. {   SBYTE i, player, which, x, xx, y, yy;
  2157.     UBYTE thissy;
  2158.  
  2159.     /* decrement worm strength */
  2160.  
  2161.     for (player = 0; player <= 3; player++)
  2162.         if (worm[player].lives > 0 && (ice == -1 || ice == player))
  2163.         {   if (worm[player].bias > 0)
  2164.             {   worm[player].bias--;
  2165.                 stat(player, BIAS);
  2166.             }
  2167.             if (worm[player].cutter > 0)
  2168.             {   worm[player].cutter--;
  2169.                 icon(player, CUTTER);
  2170.             }                
  2171.             if (worm[player].freedom > 0)
  2172.             {   worm[player].freedom--;
  2173.                 icon(player, FREEDOM);
  2174.             }
  2175.             if (worm[player].ice > 0)
  2176.             {    worm[player].ice--;
  2177.                 icon(player, ICE);
  2178.                 for (which = 0; which <= 3; which++)
  2179.                     if (player != which)
  2180.                         worm[which].pos = -1;
  2181.                 ice = -1;
  2182.                 icon(player, ICE);
  2183.             }
  2184.             if (worm[player].mode == ARMOUR)
  2185.             {   if (--worm[player].armour == 0)
  2186.                 {   if (worm[player].tongue > 0)
  2187.                         worm[player].mode = TONGUE;
  2188.                     else worm[player].mode = NOMODE;
  2189.                 }
  2190.                 stat(player, ARMOUR);
  2191.             } elif (worm[player].mode == TONGUE)
  2192.             {   if (--worm[player].tongue == 0)
  2193.                 {   if (worm[player].armour > 0)
  2194.                         worm[player].mode = ARMOUR;
  2195.                     else worm[player].mode = NOMODE;
  2196.                 }
  2197.                 stat(player, TONGUE);
  2198.         }   }
  2199.  
  2200.     /* blank out old causes */
  2201.  
  2202.     for (player = 0; player <= 3; player++)
  2203.     {   if (worm[player].lives > 0 && r > worm[player].causewait)
  2204.         {   drawcause(player, BLACK);
  2205.             worm[player].causewait = (ULONG) -1; /* most future time possible */
  2206.     }   }
  2207.  
  2208. if (ice == -1)
  2209. {   if (level)
  2210.     {    /* decrement orb strength */
  2211.         for (which = 0; which <= CREATURES; which++)
  2212.             if (creature[which].alive && creature[which].species == ORB)
  2213.                 if (creature[which].mode == ARMOUR)
  2214.                 {   if (--creature[which].armour == 0)
  2215.                         if (creature[which].tongue > 0)
  2216.                             creature[which].mode = TONGUE;
  2217.                         else creature[which].mode = NOMODE;
  2218.                 } elif (creature[which].mode == TONGUE)
  2219.                 {   if (--creature[which].tongue == 0)
  2220.                         if (creature[which].armour > 0)
  2221.                             creature[which].mode = ARMOUR;
  2222.                         else creature[which].mode = NOMODE;
  2223.                 }
  2224.  
  2225.         /* create goats */
  2226.         if
  2227.         (   (!(rand() % freq))
  2228.         &&  findempty(&x, &y, FIRSTGOAT, LASTGOAT)
  2229.         &&  field[x][y] != GOAT
  2230.         )
  2231.         {   for (i = 0; i <= CREATURES; i++)
  2232.             {   if (!creature[i].alive)
  2233.                 {   effect(FXBORN_GOAT);
  2234.                     creature[i].x = x;
  2235.                     creature[i].y = y;
  2236.                     creature[i].alive = TRUE;
  2237.                     creature[i].species = GOAT;
  2238.                     creature[i].last = creature[i].oldlast = field[x][y];
  2239.                     creature[i].speed = (SBYTE) atleast(GOATSPEED - (level / 2), 2);
  2240.                     creature[i].visible = TRUE;
  2241.                     change(x, y, GOAT);
  2242.                     break;
  2243.         }   }   }
  2244.  
  2245.         /* create orbs */
  2246.         if
  2247.         (   (!(rand() % freq))
  2248.          && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY)
  2249.         )
  2250.         {   for (i = 0; i <= CREATURES; i++)
  2251.             {   if (!creature[i].alive)
  2252.                 {   effect(FXBORN_ORB);
  2253.                     creature[i].deltax = (rand() % 2) * 2 - 1;
  2254.                     creature[i].deltay = (rand() % 2) * 2 - 1;
  2255.                     creature[i].score = 0;
  2256.                     creature[i].alive = TRUE;
  2257.                     creature[i].armour = 0;
  2258.                     creature[i].tongue = 0;
  2259.                     creature[i].mode = NOMODE;
  2260.                     creature[i].speed = (SBYTE) atleast(ORBSPEED - (level / 2), 2);
  2261.                     creature[i].species = ORB;
  2262.                     creature[i].explode = FALSE;
  2263.                     creature[i].multi = 1;
  2264.                     creature[i].x = x;
  2265.                     creature[i].y = y;
  2266.                     creature[i].last = EMPTY;
  2267.                     creature[i].visible = TRUE;
  2268.                     change(x, y, ORB);
  2269.                     break;
  2270.         }   }   }
  2271.  
  2272.         /* create dogs */
  2273.         if ((!(rand() % freq)) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2274.         {   for (i = 0; i <= CREATURES; i++)
  2275.                 if (!(creature[i].alive))
  2276.                 {   creature[i].x = x;
  2277.                     creature[i].y = y;
  2278.                     creature[i].last = EMPTY;
  2279.                     creature[i].speed = (SBYTE) atleast(DOGSPEED - (level / 2), 2);
  2280.                     creature[i].visible = TRUE;
  2281.                     creature[i].deltax = 0;
  2282.                     creature[i].deltay = 0;
  2283.                     creature[i].species = DOG;
  2284.                     creature[i].alive = TRUE;
  2285.                     creature[i].pos = -1;
  2286.                     creature[i].dormant = DORMANT; /* dormant */
  2287.                     field[x][y] = DOG;
  2288.                     draw(x, y, DOGDORMANT);
  2289.                     break;
  2290.         }       }
  2291.  
  2292.         /* create slime */
  2293.         if ((!(rand() % (freq * 2))) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2294.             change(x, y, SLIME);
  2295.  
  2296.         /* grow slime */
  2297.         if (!(rand() % (freq * 2)))
  2298.         {   for (x = 0; x <= FIELDX; x++)
  2299.                 for (y = 0; y <= FIELDY; y++)
  2300.                     if (field[x][y] == SLIME)
  2301.                         for (xx = x - 1; xx <= x + 1; xx++)
  2302.                             for (yy = y - 1; yy <= y + 1; yy++)
  2303.                                 if (valid(xx, yy) && field[xx][yy] == EMPTY && !(rand() % 2))
  2304.                                     field[xx][yy] = TEMPSLIME;
  2305.             for (x = 0; x <= FIELDX; x++)
  2306.                 for (y = 0; y <= FIELDY; y++)
  2307.                     if (field[x][y] == TEMPSLIME)
  2308.                         change(x, y, SLIME);
  2309.         }
  2310.  
  2311.         /* create timebombs */
  2312.         if ((!(rand() % (freq * 8))) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2313.         {   for (i = 0; i <= CREATURES; i++)
  2314.             if (!(creature[i].alive))
  2315.             {   creature[i].x = x;
  2316.                 creature[i].y = y;
  2317.                 creature[i].last = EMPTY;
  2318.                 creature[i].speed = (SBYTE) atleast(TIMEBOMBSPEED - (level / 2), 2);
  2319.                 creature[i].visible = TRUE;
  2320.                 creature[i].deltax = 0;
  2321.                 creature[i].deltay = 0;
  2322.                 creature[i].species = TIMEBOMB;
  2323.                 creature[i].alive = TRUE;
  2324.                 creature[i].time = 10;
  2325.                 field[x][y] = TIMEBOMB;
  2326.                 draw(x, y, ZERO + 9);
  2327.                 break;
  2328.     }   }   }
  2329.  
  2330.     /* create drips */
  2331.     if
  2332.     (   (level && (!(rand() % freq)))
  2333.      || ((!level) && leveltype == DRIP && (!(rand() % FREQ_DRIP)))
  2334.     )
  2335.     {   x = (rand() % (FIELDX + 1));
  2336.         y = (rand() % 3);
  2337.         thissy = field[x][y];
  2338.         if (thissy >= FIRSTEMPTY && thissy <= LASTEMPTY)
  2339.         {   for (i = 0; i <= CREATURES; i++)
  2340.             {   if (!creature[i].alive)
  2341.                 {   effect(FXBORN_DRIP);
  2342.                     creature[i].alive      = TRUE;
  2343.                     creature[i].last       = EMPTY;
  2344.                     creature[i].species    = DRIP;
  2345.                     creature[i].type       = rand() % 4;
  2346.                     creature[i].x          = x;
  2347.                     creature[i].y          = y;
  2348.                     creature[i].deltax     = 0;
  2349.                     creature[i].deltay     = 1;
  2350.                     creature[i].visible    = TRUE;
  2351.                     if (level)
  2352.                         creature[i].speed  = (SBYTE) atleast(DRIPSPEED - (level / 2), 2);
  2353.                     else creature[i].speed = BONUSDRIPSPEED;
  2354.                     change(x, y, FIRSTDRIP + creature[which].type);
  2355.                     break;
  2356.     }   }   }   }
  2357.  
  2358.     /* create penguins */
  2359.     if
  2360.     ((   (  level  && !(rand() % freq))
  2361.      ||  ((!level) && leveltype == PENGUIN && (!(rand() % FREQ_PENGUIN)))
  2362.      ) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY)
  2363.     )
  2364.     {   for (i = 0; i <= CREATURES; i++)
  2365.             if (!(creature[i].alive))
  2366.             {   effect(FXBORN_PENGUIN);
  2367.                 creature[i].x = x;
  2368.                 creature[i].y = y;
  2369.                 creature[i].last = EMPTY;
  2370.                 if (level)
  2371.                     creature[i].speed = (SBYTE) atleast(PENGUINSPEED - (level / 2), 2);
  2372.                 else creature[i].speed = BONUSPENGUINSPEED;
  2373.                 creature[i].visible = TRUE;
  2374.                 creature[i].deltax = 0;
  2375.                 creature[i].deltay = 0;
  2376.                 creature[i].species = PENGUIN;
  2377.                 creature[i].alive = TRUE;
  2378.                 change(x, y, PENGUIN);
  2379.                 break;
  2380.     }       }
  2381.  
  2382.     /* create clouds */
  2383.     if (level && (!(rand() % freq)))
  2384.     {   x = (rand() % (FIELDX - 1)) + 1;
  2385.         y = (rand() % (FIELDY - 1)) + 1;
  2386.         /* If you create clouds at an extreme horizontal position
  2387.         (0 or FIELDX), will cause a crash because the deltas will be
  2388.         wrong. */
  2389.         thissy = field[x][y];
  2390.         if (thissy >= FIRSTEMPTY && thissy <= LASTEMPTY)
  2391.         {   for (i = 0; i <= CREATURES; i++)
  2392.             {   if (!creature[i].alive)
  2393.                 {   creature[i].alive       = TRUE;
  2394.                     creature[i].last        = EMPTY;
  2395.                     creature[i].species     = CLOUD;
  2396.                     creature[i].x           = x;
  2397.                     creature[i].y           = y;
  2398.                     if (x < FIELDX / 2)
  2399.                         creature[i].deltax  = 1;
  2400.                     else creature[i].deltax = -1;
  2401.                     creature[i].deltay      = 0;
  2402.                     creature[i].visible     = TRUE;
  2403.                     creature[i].speed       = (SBYTE) atleast(CLOUDSPEED - (level / 2), 3);
  2404.                     change(x, y, CLOUD);
  2405.                     break;
  2406.     }   }   }   }
  2407.  
  2408.     /* create objects */
  2409.     for (which = 0; which <= LASTOBJECT; which++)
  2410.         if (level || leveltype != TREASURE || which == TREASURE)
  2411.         {   if (!(rand() % object[which].freq) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2412.                 change(x, y, which);
  2413.         } elif (!(rand() % (object[which].freq / 10)) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2414.             change(x, y, which);
  2415.  
  2416.     /* create teleports */
  2417.     if (!(rand() % FREQ_TELEPORT)
  2418.     && !teleport[level][2].alive
  2419.     && findempty(&(teleport[level][2].x), &(teleport[level][2].y), FIRSTEMPTY, LASTEMPTY)
  2420.     && findempty(&(teleport[level][3].x), &(teleport[level][3].y), FIRSTEMPTY, LASTEMPTY)
  2421.     && (teleport[level][2].x != teleport[level][3].x || teleport[level][2].y != teleport[level][3].y))
  2422.     {   teleport[level][2].alive = TRUE;
  2423.         teleport[level][3].alive = TRUE;
  2424.         change(teleport[level][2].x, teleport[level][2].y, TELEPORT);
  2425.         change(teleport[level][3].x, teleport[level][3].y, TELEPORT);
  2426. }   }
  2427. }
  2428.  
  2429. MODULE SBYTE speedup(SBYTE speed, ABOOL nitro)
  2430. {    speed /= 2;
  2431.     if (speed < FAST)
  2432.         speed = FAST;
  2433.     return(speed);
  2434. }
  2435.  
  2436. MODULE ULONG squareblast(SBYTE type, SBYTE player, SBYTE thissy, SBYTE x, SBYTE y, ABOOL cutter)
  2437. {   SBYTE which;
  2438.     ULONG score = 0;
  2439.     SBYTE filler;
  2440.  
  2441.     if (type == HEAD && worm[player].bias)
  2442.         filler = SILVER;
  2443.     else filler = EMPTY;
  2444.  
  2445.     if (thissy <= LASTOBJECT)
  2446.     {   if (!cutter)
  2447.             change(x, y, filler);
  2448.     } elif (thissy >= FIRSTTAIL && thissy <= LASTTAIL)
  2449.         change(x, y, filler);
  2450.     elif (thissy == ORB)
  2451.     {   which = whichcreature(x, y, ORB, 255);
  2452.         if (creature[which].mode != ARMOUR)
  2453.         {   effect(FXDEATH_ORB);
  2454.             creature[which].alive = FALSE;
  2455.             score = creature[which].score;
  2456.             if (type == HEAD && worm[player].bias)
  2457.                 worm[player].lives += ORBBLOOD;
  2458.             change(x, y, BONUS);
  2459.         } else effect(FXUSE_ARMOUR);
  2460.     } elif (thissy >= FIRSTDRIP && thissy <= LASTDRIP)
  2461.     {   creature[whichcreature(x, y, DRIP, 255)].alive = FALSE;
  2462.         change(x, y, filler);
  2463.     } elif (thissy >= FIRSTHEAD && thissy <= LASTHEAD)
  2464.     {   if (type != HEAD || player != thissy - FIRSTHEAD)
  2465.             if (worm[thissy - FIRSTHEAD].mode != ARMOUR)
  2466.             {   worm[thissy - FIRSTHEAD].cause = BOMB;
  2467.                 worm[thissy - FIRSTHEAD].alive = FALSE;
  2468.                 stat(thissy - FIRSTHEAD, LIFE);
  2469.                 if (type == HEAD)
  2470.                     worm[thissy - FIRSTHEAD].victor = player;
  2471.                 else
  2472.                 {   worm[thissy - FIRSTHEAD].victor = -1;
  2473.                     score = KILLWORM; // worms will get this bonus from death(), so it is not given for them here.
  2474.             }   }
  2475.             else effect(FXUSE_ARMOUR);
  2476.     } elif (thissy >= FIRSTMISSILE && thissy <= LASTMISSILE)
  2477.     {   if (type != HEAD || player != thissy - FIRSTMISSILE)
  2478.         {   creature[whichcreature(x, y, MISSILE, 255)].alive = FALSE;
  2479.             change(x, y, filler);
  2480.     }    }
  2481.     elif (thissy == PENGUIN)
  2482.     {    creature[whichcreature(x, y, PENGUIN, 255)].alive = FALSE;
  2483.         change(x, y, filler);
  2484.     } elif (thissy == FRAGMENT)
  2485.     {    creature[whichcreature(x, y, FRAGMENT, 255)].alive = FALSE;
  2486.         change(x, y, filler);
  2487.     } elif (thissy == GOAT)
  2488.     {   creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  2489.         change(x, y, BONUS);
  2490.     }
  2491.     return(score);
  2492. }
  2493.  
  2494. void timeloop(void)
  2495. {           TEXT  timedisplay[5] = {"#:##"};
  2496.     PERSIST ABOOL outoftime      = FALSE;
  2497.             UBYTE i;
  2498.  
  2499.     secondsleft = atleast(secondsleft, 0);
  2500.     timedisplay[0] = 48 +  (secondsleft / 60);
  2501.     timedisplay[2] = 48 + ((secondsleft % 60) / 10);
  2502.     timedisplay[3] = 48 + ((secondsleft % 60) % 10);
  2503.  
  2504.     if (!level)
  2505.     {   say(timedisplay, worm[treasurer].colour);
  2506.         if (!secondsleft)
  2507.         {   level = reallevel + 1;
  2508.             secondsleft = SECONDSPERLEVEL;
  2509.             newlevel(treasurer);
  2510.     }   }
  2511.     elif (!secondsleft)
  2512.     {   if (!outoftime)
  2513.         {   effect(FXSIREN);
  2514.             say("Out of time!", WHITE);
  2515.             outoftime = TRUE;
  2516.             freq /= 2;
  2517.             for (i = 0; i <= CREATURES; i++)
  2518.                 if (creature[i].alive)
  2519.                     creature[i].speed = speedup(creature[i].speed, TRUE);
  2520.     }   }
  2521.     else
  2522.     {    outoftime = FALSE;
  2523.         say(timedisplay, WHITE);
  2524. }    }
  2525.  
  2526. void train(SCANCODE scancode)
  2527. {   SBYTE i, x, y;
  2528.  
  2529.     switch(scancode)
  2530.     {
  2531.     case HELP:
  2532.         trainer = !trainer;
  2533.     break;
  2534.     case NUMERICSLASH:
  2535.         /* Complete the level. */
  2536.         if (trainer)
  2537.         {   trainer = FALSE;
  2538.             if (worm[1].lives > 0)
  2539.             for (i = 0; i <= LETTERS; i++)
  2540.             {   letters[1][i] = TRUE;
  2541.                 drawletter(1, FIRSTLETTER + i, NORMAL);
  2542.         }   }
  2543.     break;
  2544.     case NUMERICASTERISK:
  2545.         /* field[][] dump, for debugging purposes. */
  2546.         for (x = 0; x <= FIELDX; x++)
  2547.             for (y = 0; y <= FIELDY; y++)
  2548.                 draw(x, y, field[x][y]);
  2549.         anykey(FALSE);
  2550.     break;
  2551.     case NUMERICPLUS:
  2552.         if (trainer)
  2553.         {   trainer = FALSE;
  2554.             say("Bianca is the best!", PURPLE);
  2555.             anykey(FALSE);
  2556.             if (worm[1].lives > 0)
  2557.             {   worm[1].lives = LIVESLIMIT;
  2558.                 stat(1, LIFE);
  2559.                 worm[1].tongue = MODELIMIT;
  2560.                 worm[1].mode = TONGUE;
  2561.                 stat(1, TONGUE);
  2562.                 worm[1].bias = BIASLIMIT;
  2563.                 stat(1, BIAS);
  2564.                 worm[1].ammo = AMMOLIMIT;
  2565.                 stat(1, AMMO);
  2566.                 worm[1].power = POWERLIMIT;
  2567.                 stat(1, POWER);
  2568.                 worm[1].nitro = TRUE;
  2569.                 stat(1, NITRO);
  2570.                 worm[1].affixer = TRUE;
  2571.                 icon(1, AFFIXER);
  2572.                 worm[1].remnants = TRUE;
  2573.                 icon(1, REMNANTS);
  2574.                 worm[1].sideshot = TRUE;
  2575.                 icon(1, SIDESHOT);
  2576.                 worm[1].pusher = TRUE;
  2577.                 icon(1, PUSHER);
  2578.                 worm[1].cutter = 100;
  2579.                 icon(1, CUTTER);
  2580.                 trainer = FALSE;
  2581.         }   }
  2582.     break;
  2583.     default:
  2584.     break;
  2585. }   }
  2586.  
  2587. MODULE void turnworm(SBYTE player, SBYTE deltax, SBYTE deltay)
  2588. {
  2589. if (worm[player].nitro || !deltax || !deltay)
  2590. {    if (worm[player].deltax == deltax && worm[player].deltay == deltay)
  2591.     {    worm[player].speed = speedup(worm[player].speed, worm[player].nitro);
  2592.         stat(player, NITRO);
  2593.     } elif (worm[player].deltax == -deltax && worm[player].deltay == -deltay)
  2594.         {       worm[player].speed = slowdown(worm[player].speed, worm[player].nitro);
  2595.         stat(player, NITRO);
  2596.     } else
  2597.     {    worm[player].deltax = deltax;
  2598.         worm[player].deltay = deltay;
  2599. }    }
  2600. }
  2601.  
  2602. void updatesquare(SBYTE x, SBYTE y)
  2603. {    SBYTE    which;
  2604.  
  2605.     if (startx[level] == x && starty[level] == y)
  2606.         draw(x, y, START);
  2607.     elif (board[level][x][y] == TELEPORT)
  2608.     {    for (which = 0; which <= 1; which++)
  2609.             if (teleport[level][which].alive && teleport[level][which].x == x && teleport[level][which].y == y)
  2610.                 draw(x, y, ONE + which);
  2611.     } else draw(x, y, board[level][x][y]);
  2612. }
  2613.  
  2614. SBYTE valid(SBYTE x, SBYTE y)
  2615. {    if (x >= 0 && x <= FIELDX && y >= 0 && y <= FIELDY)
  2616.         return(TRUE);
  2617.     else
  2618.         return(FALSE);
  2619. }
  2620.  
  2621. MODULE UBYTE whichcreature(SBYTE x, SBYTE y, UBYTE species, UBYTE exception)
  2622. {   UBYTE i;    
  2623.  
  2624.     for (i = 0; i <= CREATURES; i++)
  2625.         if
  2626.         (   creature[i].alive
  2627.          && creature[i].x == x
  2628.          && creature[i].y == y
  2629.          && creature[i].species == species
  2630.          && i != exception
  2631.         )
  2632.             return i;
  2633.     return 255; /* error code
  2634.  */
  2635. }
  2636. MODULE SBYTE whichteleport(SBYTE x, SBYTE y)
  2637. {   SBYTE which;
  2638.  
  2639.     for (which = 0; which <= 3; which++)
  2640.         if (teleport[level][which].alive && teleport[level][which].x == x && teleport[level][which].y == y)
  2641.             return((SBYTE) which);
  2642.     return((SBYTE) -1); /* error code */
  2643. }
  2644.  
  2645. MODULE void wormbullet(SBYTE player)
  2646. {   ABOOL   finished,
  2647.             flag            = FALSE,
  2648.             ok              = FALSE,
  2649.             lettered        = FALSE;
  2650.     LONG    score;
  2651.     SBYTE   distance,
  2652.             thissy,
  2653.             i, j,
  2654.             x, y;
  2655.  
  2656.     if (!worm[player].ammo)
  2657.     {   stat(player, BONUS);
  2658.     if (worm[player].speed == FAST)
  2659.         distance = FASTDISTANCE;
  2660.     elif (worm[player].speed == NORMAL)
  2661.        distance = NORMALDISTANCE;
  2662.         elif (worm[player].speed == SLOW)
  2663.        distance = SLOWDISTANCE;
  2664.         else
  2665.         {  // assert(worm[player].speed == VERYSLOW);
  2666.            distance = VERYSLOWDISTANCE;
  2667.         }
  2668.  
  2669.     /* check for metal */
  2670.  
  2671.     for (i = 1; i < distance; i++)
  2672.     {   x = xwrap(worm[player].x + (i * worm[player].deltax));
  2673.         y = ywrap(worm[player].y + (i * worm[player].deltay));
  2674.         if (field[x][y] == METAL)
  2675.         flag = TRUE;
  2676.     }
  2677.  
  2678.     if (!flag)
  2679.         {   // assert(abs(worm[player].deltax) <= 1 && abs(worm[player].deltay) <= 1);
  2680.         x = xwrap(worm[player].x + (worm[player].deltax * distance));
  2681.         y = ywrap(worm[player].y + (worm[player].deltay * distance));
  2682.         thissy = field[x][y];
  2683.         if (thissy == TELEPORT)
  2684.         {   i = whichteleport(x, y);
  2685.             if (!blocked(i, worm[player].deltax, worm[player].deltay))
  2686.             ok = TRUE;
  2687.         }
  2688.             if (ok || ((thissy < STONE || thissy > GOAT) && thissy != METAL))
  2689.             {   effect(FXDO_JUMP);
  2690.             worm[player].deltax *= distance;
  2691.             worm[player].deltay *= distance;
  2692.     }   }   }
  2693.     else
  2694.     {   effect(FXUSE_AMMO);
  2695.         worm[player].ammo--;
  2696.         stat(player, AMMO);
  2697.         if (worm[player].bias)
  2698.             createmissile(player, worm[player].x, worm[player].y);
  2699.  
  2700.         if (worm[player].sideshot)
  2701.         {   bullet[7].alive      = bullet[8].alive      = TRUE;
  2702.             bullet[7].teleported = bullet[8].teleported = 0;
  2703.             bullet[7].visible    = bullet[8].visible    = TRUE;
  2704.             bullet[7].reflected  = bullet[8].reflected  = FALSE;
  2705.             bullet[7].x          = bullet[8].x          = worm[player].x;
  2706.             bullet[7].y          = bullet[8].y          = worm[player].y;
  2707.             if (!worm[player].deltax && worm[player].deltay)
  2708.             {   bullet[7].deltax = -1;
  2709.                 bullet[8].deltax = 1;
  2710.                 bullet[7].deltay = bullet[8].deltay = 0;
  2711.             } elif (worm[player].deltax && !worm[player].deltay)
  2712.             {   bullet[7].deltax = bullet[8].deltax = 0;
  2713.                 bullet[7].deltay = -1;
  2714.                 bullet[8].deltay = 1;
  2715.             } else /* worm is diagonal */
  2716.             {   if (worm[player].deltax == worm[player].deltay)
  2717.                 {   bullet[7].deltax = 1;
  2718.                     bullet[7].deltay = -1;
  2719.                 } else
  2720.                 {   bullet[7].deltax = -1;
  2721.                     bullet[7].deltay = -1;
  2722.                 }
  2723.                 bullet[8].deltax = -bullet[7].deltax;
  2724.                 bullet[8].deltay = -bullet[7].deltay;
  2725.         }   }
  2726.  
  2727.         for (i = 0; i <= worm[player].power; i++)
  2728.         {   bullet[i].alive      = TRUE;
  2729.             bullet[i].teleported = 0;
  2730.             bullet[i].visible    = TRUE;
  2731.             bullet[i].reflected  = FALSE;
  2732.             bullet[i].deltax     = worm[player].deltax;
  2733.             bullet[i].deltay     = worm[player].deltay;
  2734.             if (i % 2 == 0)
  2735.                 distance = i / 2;
  2736.             else distance = -((i + 1) / 2);
  2737.             if (worm[player].deltax == 0)
  2738.             {   bullet[i].x = worm[player].x + distance;
  2739.                 bullet[i].y = worm[player].y;
  2740.             } elif (worm[player].deltay == 0)
  2741.             {   bullet[i].x = worm[player].x;
  2742.                 bullet[i].y = worm[player].y + distance;
  2743.             } else
  2744.             {   switch (i)
  2745.                 {
  2746.                 case 0:
  2747.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2748.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2749.                 break;
  2750.                 case 1:
  2751.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2752.                     bullet[i].y = worm[player].y;
  2753.                 break;
  2754.                 case 2:
  2755.                     bullet[i].x = worm[player].x;
  2756.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2757.                 break;
  2758.                 case 3:
  2759.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2760.                     bullet[i].y = worm[player].y;
  2761.                 break;
  2762.                 case 4:
  2763.                     bullet[i].x = worm[player].x;
  2764.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2765.                 break;
  2766.                 case 5:
  2767.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2768.                     bullet[i].y = worm[player].y - worm[player].deltay;
  2769.                 break;
  2770.                 case 6:
  2771.                     bullet[i].x = worm[player].x - worm[player].deltax;
  2772.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2773.                 break;
  2774.                 default:
  2775.                 break;
  2776.         }   }   }
  2777.  
  2778.         /* Bullets are now set up. */
  2779.  
  2780.         score = 0;
  2781.         finished = FALSE;
  2782.         while (!finished)
  2783.         {   finished = TRUE;
  2784.             for (i = 0; i <= 8; i++)
  2785.             {   if (bullet[i].alive)
  2786.                 {   finished = FALSE;
  2787.                     if (bullet[i].reflected)
  2788.                     {   bullet[i].x -= bullet[i].deltax;
  2789.                         bullet[i].y -= bullet[i].deltay;
  2790.                     } else
  2791.                     {   bullet[i].x += bullet[i].deltax;
  2792.                         bullet[i].y += bullet[i].deltay;
  2793.                     }
  2794.                     x = bullet[i].x;
  2795.                     y = bullet[i].y;
  2796.                     thissy = field[x][y];
  2797.                     if (!(valid(x, y)))
  2798.                         bullet[i].alive = FALSE;
  2799.                     elif (x == worm[player].x && y == worm[player].y)
  2800.                     {   /* hit by own bullet */
  2801.                         bullet[i].alive = FALSE;
  2802.                         if (worm[player].mode != ARMOUR)
  2803.                         {   worm[player].cause = FIRSTFIRE + player;
  2804.                             worm[player].victor = -1;
  2805.                             worm[player].alive = FALSE;
  2806.                     }   }
  2807.                     elif (thissy >= FIRSTHEAD && thissy <= LASTHEAD)
  2808.                     {   if (worm[thissy - FIRSTHEAD].mode != ARMOUR)
  2809.                         {   worm[thissy - FIRSTHEAD].cause = FIRSTFIRE + player;
  2810.                             worm[thissy - FIRSTHEAD].victor = player;
  2811.                             worm[thissy - FIRSTHEAD].alive = FALSE;
  2812.                             if (player != thissy - FIRSTHEAD)
  2813.                                 score += KILLWORM + HITSHOT;
  2814.                         } else effect(FXUSE_ARMOUR);
  2815.                         bullet[i].alive = FALSE;
  2816.                     } elif (thissy >= FIRSTPROTECTOR && thissy <= LASTPROTECTOR)
  2817.                     {   if (player != thissy - FIRSTPROTECTOR)
  2818.                         {   effect(FXUSE_PROTECTOR);
  2819.                             bullet[i].alive = FALSE;
  2820.                         } else bullet[i].visible = FALSE;
  2821.                     } elif (thissy >= FIRSTMISSILE && thissy <= LASTMISSILE)
  2822.                     {   if (player != thissy - FIRSTMISSILE)
  2823.                             creature[whichcreature(x, y, MISSILE, 255)].alive = FALSE;
  2824.                         else bullet[i].visible = FALSE;
  2825.                     } elif (thissy >= FIRSTDRIP && thissy <= LASTDRIP)
  2826.                     {   j = whichcreature(x, y, DRIP, 255);
  2827.                         creature[j].alive = FALSE;
  2828.                     } elif (thissy >= FIRSTLETTER && thissy <= LASTLETTER)
  2829.                     {   wormletter(player, thissy);
  2830.                         lettered = TRUE;
  2831.                     } else
  2832.                     {   switch(thissy)
  2833.                         {
  2834.                         case METAL:
  2835.                             if (bullet[i].reflected)
  2836.                                 bullet[i].alive = FALSE;
  2837.                             else
  2838.                             {   bullet[i].reflected = TRUE;
  2839.                                 bullet[i].x -= bullet[i].deltax * 2;
  2840.                                 bullet[i].y -= bullet[i].deltay * 2;
  2841.                             }
  2842.                             break;
  2843.                         case STONE:
  2844.                         case WHIRLWIND:
  2845.                             bullet[i].alive = FALSE;
  2846.                         break;
  2847.                         case ORB:
  2848.                             bullet[i].alive = FALSE;
  2849.                             j = whichcreature(x, y, ORB, 255);
  2850.                             if (creature[j].mode != ARMOUR)
  2851.                             {   creature[j].explode = TRUE;
  2852.                                 score += creature[j].score + HITSHOT;
  2853.                                 if (worm[player].bias)
  2854.                                     worm[player].lives += ORBBLOOD;
  2855.                             } else effect(FXUSE_ARMOUR);
  2856.                         break;
  2857.                         case TELEPORT:
  2858.                             j = whichteleport(bullet[i].x, bullet[i].y);
  2859.                             if (bullet[i].teleported == 2)
  2860.                                 bullet[i].alive = FALSE;
  2861.                             else
  2862.                             {   effect(FXUSE_TELEPORT);
  2863.                                 bullet[i].visible = FALSE;
  2864.                                 bullet[i].teleported++;
  2865.                                 bullet[i].x = teleport[level][partner(j)].x;
  2866.                                 bullet[i].y = teleport[level][partner(j)].y;
  2867.                                 score += TELPOINT;
  2868.                             }
  2869.                         break;
  2870.                         case WOOD:
  2871.                             if (!worm[player].bias)
  2872.                                 bullet[i].alive = FALSE;
  2873.                         break;
  2874.                         case GOAT:
  2875.                             creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  2876.                             change(x, y, BONUS);
  2877.                             score += KILLGOAT + HITSHOT;
  2878.                             if (worm[player].bias)
  2879.                                 worm[player].lives += GOATBLOOD;
  2880.                             bullet[i].alive = FALSE;
  2881.                         break;
  2882.                         case SKULL:
  2883.                             bullet[i].alive = FALSE;
  2884.                         break;
  2885.                         case FRAGMENT:
  2886.                             bullet[i].alive = FALSE;
  2887.                             creature[whichcreature(x, y, FRAGMENT, 255)].alive = FALSE;
  2888.                             change(x, y, EMPTY);
  2889.                         break;
  2890.                         case PENGUIN:
  2891.                             bullet[i].alive = FALSE;
  2892.                             creature[whichcreature(x, y, PENGUIN, 255)].alive = FALSE;
  2893.                             change(x, y, EMPTY);
  2894.                             score += KILLPENGUIN + HITSHOT;
  2895.                             if (worm[player].bias)
  2896.                                 worm[player].lives += PENGUINBLOOD;
  2897.                         break;
  2898.                         case DOG:
  2899.                             bullet[i].alive = FALSE;
  2900.                         break;
  2901.                         case CLOUD:
  2902.                             creature[whichcreature(x, y, CLOUD, 255)].alive = FALSE;
  2903.                             change(x, y, EMPTY);
  2904.                         break;
  2905.                         case TIMEBOMB:
  2906.                             creature[whichcreature(x, y, TIMEBOMB, 255)].alive = FALSE;
  2907.                             bombblast(BOMB, 0, x, y);
  2908.                             change(x, y, EMPTY);
  2909.                         break;
  2910.                         default:
  2911.                         break;
  2912.                     }   }
  2913.  
  2914.                     // x and y need this refreshing here
  2915.                     x = bullet[i].x;
  2916.                     y = bullet[i].y;
  2917.                     if (bullet[i].alive && bullet[i].visible)
  2918.                     {   draw(x, y, FIRSTFIRE + player);
  2919.                         if (worm[player].remnants)
  2920.                             field[x][y] = FIRSTFIRE + player;
  2921.                         elif (bullet[i].teleported)
  2922.                             change(x, y, GOLD);
  2923.                         else change(x, y, EMPTY);
  2924.         }   }   }   }
  2925.         if (lettered)
  2926.             putletter(player);
  2927.         wormscore(player, score);
  2928.         if (worm[player].bias)
  2929.             stat(player, LIFE);
  2930.         clearkybd();
  2931. }   }
  2932.  
  2933. MODULE void wormletter(SBYTE player, SBYTE c)
  2934. {   switch(c)
  2935.     {
  2936.     case GREEN_C:
  2937.         effect(FX_C);
  2938.     break;
  2939.     case RED_O:
  2940.         effect(FX_O);
  2941.     break;
  2942.     case BLUE_M:
  2943.         effect(FX_M);
  2944.     break;
  2945.     case YELLOW_P:
  2946.        effect(FX_P);
  2947.     break;
  2948.     case GREEN_L:
  2949.         effect(FX_L);
  2950.     break;
  2951.     case BLUE_T:
  2952.         effect(FX_T);
  2953.     break;
  2954.     default:
  2955.         // assert(c == RED_E || c == YELLOW_E);
  2956.         effect(FX_E);
  2957.     break;
  2958.     }
  2959.     letters[player][c - FIRSTLETTER] = TRUE;
  2960.     drawletter(player, c, NORMAL);
  2961.     wormscore(player, LETTERPOINT);
  2962. }
  2963.  
  2964. /* NAME     wormloop -- controls worms and protectors
  2965. SYNOPSIS    wormloop(SBYTE);
  2966. FUNCTION    Amiga-worm thinking, processing one keystroke from the
  2967.             worm's queue, all the worm's protectors' control, the
  2968.             worm's control.
  2969. MODULE      engine.c */
  2970.  
  2971. MODULE void wormloop(SBYTE player)
  2972. {   AUTO    ABOOL enclosed = FALSE, ok;
  2973.     AUTO    SBYTE bestx, besty, c, d, dirx, diry, i, k,
  2974.                   thisprot, x, y, leftx, rightx, topy,
  2975.                   bottomy;
  2976.     AUTO    SWORD bestgood, good;
  2977.     AUTO    UBYTE interior;
  2978.     AUTO    ULONG score = 0;
  2979.     PERSIST struct
  2980.     {   SBYTE deltax[4], deltay[4];
  2981.     } deltas[4] =
  2982.     { { { 0, -1,  0,  1}, // northwest
  2983.         {-1,  0,  1,  0}
  2984.       },
  2985.       { { 0,  1,  0, -1}, // northeast
  2986.         {-1,  0,  1,  0}
  2987.       },
  2988.       { { 0,  1,  0, -1}, // southeast
  2989.         { 1,  0, -1,  0}
  2990.       },
  2991.       { { 0, -1,  0,  1}, // southwest
  2992.         { 1,  0, -1,  0}
  2993.     } };
  2994.     PERSIST struct
  2995.     {   SBYTE leftx, rightx, topy, bottomy;
  2996.     } enclose[4] =
  2997.     { {-127,   -1, -127,  -1 }, // northwest
  2998.       {   1,  127, -127,  -1 }, // northeast
  2999.       {   1,  127,    1, 127 }, // southeast
  3000.       {-127,   -1,    1, 127 }  // southwest
  3001.     };
  3002.  
  3003. /*    Amiga worm control
  3004.     Remove a keystroke from the worm queue
  3005.     Move worm (and add a keystroke to the dog queue)
  3006.     Check for enclosure
  3007.     Move protectors
  3008.     Collision detection */
  3009.  
  3010.     /* AI: Amiga worm control, enhanced for 6.0.
  3011.  
  3012.     Worm checks ahead, left and right one square. Assigns opinions
  3013.     to those three choices and then takes the appropriate one. */
  3014.  
  3015.     if (worm[player].control == AMIGA)
  3016.     {   if (!(rand() % 50))
  3017.             wormqueue(player, (rand() % 3) - 1, (rand() % 3) - 1);
  3018.         else
  3019.         {   bestgood = -128;
  3020.  
  3021.             for (i = 0; i <= 2; i++)
  3022.             {   switch(i)
  3023.                 {
  3024.                 case 0:
  3025.                     dirx = worm[player].deltax;
  3026.                     diry = worm[player].deltay;
  3027.                 break;
  3028.                 case 1:
  3029.                     if (worm[player].deltax == 0) /* if going north or south */
  3030.                     {   dirx = -1;                /* then look west */
  3031.                         diry = 0;
  3032.                     } else                        /* if going east or west */
  3033.                     {   dirx = 0;                 /* then look north */
  3034.                         diry = -1;
  3035.                     }
  3036.                 break;
  3037.                 case 2:
  3038.                     if (worm[player].deltax == 0) /* if going north or south */
  3039.                     {   dirx = 1;                 /* then look east */
  3040.                         diry = 0;
  3041.                     } else                        /* if going east or west */
  3042.                     {   dirx = 0;                 /* then look south */
  3043.                         diry = 1;
  3044.                     }
  3045.                 break;
  3046.                 default:
  3047.                 break;
  3048.                 }
  3049.                 c = field[xwrap(worm[player].x + dirx)][ywrap(worm[player].y + diry)];
  3050.                 if (c >= FIRSTLETTER && c <= LASTLETTER)
  3051.                     good = LETTERPOINT;
  3052.                 elif (c >= FIRSTHEAD && c <= LASTHEAD)
  3053.                     good = -55;
  3054.                 elif (c <= LASTOBJECT)
  3055.                     good = (SWORD) object[c].score;
  3056.                 elif (c == FIRSTPROTECTOR + player)
  3057.                     good = 6;
  3058.                 elif (c == FIRSTFIRE && c <= LASTFIRE)
  3059.         {   if (player == c - FIRSTFIRE)
  3060.                 good = -1;
  3061.                     else good = -70;
  3062.                 } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  3063.                 {   if (worm[player].mode == TONGUE && worm[player].tongue > 10)
  3064.                         if (player != c - FIRSTTAIL)
  3065.                             good = 10;
  3066.                         else good = -10;
  3067.                     elif (player == c - FIRSTTAIL)
  3068.                         good = -30;
  3069.                     else good = -60;
  3070.                 } else switch(c)
  3071.                 {
  3072.                 case SKULL:
  3073.                     good = 70;
  3074.                 break;
  3075.                 case GOLD:
  3076.                     good = GOLDPOINT;
  3077.                 break;
  3078.                 case SILVER:
  3079.                     good = SILVERPOINT;
  3080.                 break;
  3081.                 case EMPTY:
  3082.                     good = EMPTYPOINT;
  3083.                 break;
  3084.                 case SLIME:
  3085.                     if (worm[player].mode == ARMOUR)
  3086.                         good = -2;
  3087.                     else good = -75;
  3088.                 break;
  3089.                 case WOOD:
  3090.                     if (worm[player].mode == ARMOUR)
  3091.                         good = -2;
  3092.                     else good = -70;
  3093.                 break;
  3094.                 case STONE:
  3095.                     good = -85;
  3096.                 break;
  3097.                 case METAL:
  3098.                     good = -90;
  3099.                 break;
  3100.                 case GOAT:
  3101.                     good = -95;
  3102.                 break;
  3103.                 case WHIRLWIND:
  3104.                     good = -100;
  3105.                 break;
  3106.                 case ORB:
  3107.                     good = -45;
  3108.                 break;
  3109.                 case CLOUD:
  3110.                     good = -40;
  3111.                 break;
  3112.                 default:
  3113.                     good = -50;
  3114.                 break;
  3115.                 }
  3116.                 if (good > bestgood)
  3117.                 {   bestx = dirx;
  3118.                     besty = diry;
  3119.                     bestgood = good;
  3120.             }   }
  3121.             if (bestgood <= -80)
  3122.             {   // turn to the right
  3123.                 if (worm[player].deltax == 0) /* if going north or south */
  3124.                 {   bestx = 1;                /* then turn east */
  3125.                     besty = 0;
  3126.                 } else                        /* if going east or west */
  3127.                 {   bestx = 0;                /* then turn south */
  3128.                     besty = 1;
  3129.             }   }
  3130.             if (bestgood <= -60 && (!(rand() % 5)))
  3131.                 wormqueue(player, 0, 0);
  3132.             elif (bestgood < 0 && (!(rand() % 2)))
  3133.                 wormqueue(player, 0, 0);
  3134.             elif (bestx != worm[player].deltax || besty != worm[player].deltay)
  3135.                 wormqueue(player, bestx, besty);
  3136.     }   }
  3137.  
  3138. /* remove a keystroke from the worm queue */
  3139.  
  3140. if (worm[player].pos != -1)
  3141. {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  3142.         wormbullet(player);
  3143.     else turnworm(player, thewormqueue[player][0].deltax, thewormqueue[player][0].deltay);
  3144.     if (--worm[player].pos != -1)
  3145.         for (i = 0; i <= worm[player].pos; i++)
  3146.         {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  3147.             thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  3148. }       }
  3149.  
  3150. /* move worm */
  3151.  
  3152. change(worm[player].x, worm[player].y, worm[player].last);
  3153. worm[player].x = xwrap(worm[player].x + worm[player].deltax);
  3154. worm[player].y = ywrap(worm[player].y + worm[player].deltay);
  3155. if (worm[player].freedom)
  3156.     worm[player].last = FIRSTFIRE + player;
  3157. else worm[player].last = FIRSTTAIL + player;
  3158.  
  3159. for (i = 0; i <= CREATURES; i++)
  3160. {   if (creature[i].alive && creature[i].species == DOG && creature[i].dormant > DORMANT && creature[i].type == player)
  3161.     {   if (!worm[player].rammed)
  3162.             dogqueue(i, worm[player].deltax, worm[player].deltay);
  3163.         if (creature[i].dormant < CHASING)
  3164.         {   creature[i].dormant++;
  3165.             draw(creature[i].x, creature[i].y, DOGAWAKENING);
  3166. }   }   }
  3167.  
  3168. worm[player].rammed = FALSE;
  3169.  
  3170. /* The deltas are not changed back to the range of -1..1 until after the
  3171. dogs have looked at the queue. This enables them to jump properly. */
  3172.  
  3173. worm[player].deltax = bsign(worm[player].deltax);
  3174. worm[player].deltay = bsign(worm[player].deltay);
  3175.  
  3176. /* check for enclosure
  3177.  
  3178. #####
  3179. #...#
  3180. #...# . = interior
  3181. #...# # = tail
  3182. ####! ! = head */
  3183.  
  3184. for (interior = 2; interior <= 7; interior++) // for each size of interior
  3185. {   for (i = 0; i <= 3; i++) // four times, once for each direction
  3186.     {   x = worm[player].x;
  3187.         y = worm[player].y;
  3188.         ok = TRUE;
  3189.  
  3190.         for (k = 0; k <= interior; k++)
  3191.         {   x += deltas[i].deltax[0];
  3192.             y += deltas[i].deltay[0];
  3193.             if ((!valid(x, y)) || field[x][y] != FIRSTTAIL + player)
  3194.             {   ok = FALSE;
  3195.                 break;
  3196.         }   }
  3197.         for (k = 0; k <= interior; k++)
  3198.         {   x += deltas[i].deltax[1];
  3199.             y += deltas[i].deltay[1];
  3200.             if ((!valid(x, y)) || field[x][y] != FIRSTTAIL + player)
  3201.             {   ok = FALSE;
  3202.                 break;
  3203.         }   }
  3204.         for (k = 0; k <= interior; k++)
  3205.         {   x += deltas[i].deltax[2];
  3206.             y += deltas[i].deltay[2];
  3207.             if ((!valid(x, y)) || field[x][y] != FIRSTTAIL + player)
  3208.             {   ok = FALSE;
  3209.                 break;
  3210.         }   }
  3211.         // now the last side
  3212.         for (k = 0; k <= interior - 1; k++)
  3213.         {   x += deltas[i].deltax[3];
  3214.             y += deltas[i].deltay[3];
  3215.             if ((!valid(x, y)) || field[x][y] != FIRSTTAIL + player)
  3216.             {   ok = FALSE;
  3217.                 break;
  3218.         }   }
  3219.         if (ok)
  3220.         {   effect(FXDO_ENCLOSE);
  3221.             enclosed = TRUE;
  3222.             if (enclose[i].leftx < -1)
  3223.                 enclose[i].leftx = -interior;
  3224.             elif (enclose[i].leftx > 1)
  3225.                 enclose[i].leftx = interior + 1;
  3226.             if (enclose[i].rightx < -1)
  3227.                 enclose[i].rightx = -(interior + 1);
  3228.             elif (enclose[i].rightx > 1)
  3229.                 enclose[i].rightx = interior;
  3230.             if (enclose[i].topy < -1)
  3231.                 enclose[i].topy = -interior;
  3232.             elif (enclose[i].topy > 1)
  3233.                 enclose[i].topy = interior + 1;
  3234.             if (enclose[i].bottomy < -1)
  3235.                 enclose[i].bottomy = -(interior + 1);
  3236.             elif (enclose[i].bottomy > 1)
  3237.                 enclose[i].bottomy = interior;
  3238.  
  3239.               leftx = worm[player].x + enclose[i].leftx;
  3240.              rightx = worm[player].x + enclose[i].rightx;
  3241.                topy = worm[player].y + enclose[i].topy;
  3242.             bottomy = worm[player].y + enclose[i].bottomy;
  3243.             // assert(leftx >= 0 && rightx <= FIELDX && topy >= 0 && bottomy <= FIELDY && leftx < rightx && topy < bottomy);
  3244.             for (x = leftx; x <= rightx; x++)
  3245.                 for (y = topy; y <= bottomy; y++)
  3246.                 {   d = field[x][y];
  3247.                     if ((d >= FIRSTEMPTY && d <= LASTEMPTY) || (d >= FIRSTTAIL && d <= LASTTAIL))
  3248.                         if (worm[player].bias)
  3249.                         {    change(x, y, GOLD);
  3250.                             wormscore(player, ENCLOSUREPOINT + TURNTOGOLD);
  3251.                         } elif (player != d - FIRSTTAIL)
  3252.                         {   change(x, y, FIRSTTAIL + player);
  3253.                             wormscore(player, ENCLOSUREPOINT);
  3254. }   }   }       }        }
  3255.  
  3256. // move protectors
  3257.  
  3258. for (i = 0; i <= PROTECTORS; i++)
  3259. {   if (protector[player][i].alive)
  3260.     {   if (protector[player][i].visible)
  3261.             change(protector[player][i].x, protector[player][i].y, protector[player][i].last);
  3262.         else protector[player][i].visible = TRUE;
  3263.         protector[player][i].last = EMPTY;
  3264.         if (i == NOSE)
  3265.         {   protector[player][i].relx = worm[player].deltax * NOSEDISTANCE;
  3266.             protector[player][i].rely = worm[player].deltay * NOSEDISTANCE;
  3267.             if (!worm[player].affixer)
  3268.             {   if (worm[player].position == -1)
  3269.                     worm[player].posidir = 1;
  3270.                 elif (worm[player].position == 1)
  3271.                     worm[player].posidir = -1;
  3272.                 worm[player].position += worm[player].posidir;
  3273.                 if (worm[player].deltax == 0)
  3274.                     protector[player][i].relx = worm[player].position;
  3275.                 elif (worm[player].deltay == 0)
  3276.                     protector[player][i].rely = worm[player].position;
  3277.                 elif (worm[player].position == -1)
  3278.                     protector[player][i].relx = worm[player].deltax * (NOSEDISTANCE - 1);
  3279.                 elif (worm[player].position == 1)
  3280.                     protector[player][i].rely = worm[player].deltay * (NOSEDISTANCE - 1);
  3281.         }   }
  3282.         elif (!worm[player].affixer)
  3283.         {   if (protector[player][i].relx == 1 && protector[player][i].rely == -1)
  3284.             {   protector[player][i].deltax = 0;
  3285.                 protector[player][i].deltay = 1;
  3286.             } elif (protector[player][i].relx == 1 && protector[player][i].rely == 1)
  3287.             {   protector[player][i].deltax = -1;
  3288.                 protector[player][i].deltay = 0;
  3289.             } elif (protector[player][i].relx == -1 && protector[player][i].rely == 1)
  3290.             {   protector[player][i].deltax = 0;
  3291.                 protector[player][i].deltay = -1;
  3292.             } elif (protector[player][i].relx == -1 && protector[player][i].rely == -1)
  3293.             {   protector[player][i].deltax = 1;
  3294.                 protector[player][i].deltay = 0;
  3295.             }
  3296.             protector[player][i].relx += protector[player][i].deltax;
  3297.             protector[player][i].rely += protector[player][i].deltay;
  3298.         }
  3299.         protector[player][i].x = worm[player].x + protector[player][i].relx;
  3300.         protector[player][i].y = worm[player].y + protector[player][i].rely;
  3301.         if (!valid(protector[player][i].x, protector[player][i].y))
  3302.             protector[player][i].visible = FALSE;
  3303. }   }
  3304.  
  3305. // head collision detection
  3306. wormcol(player, worm[player].x, worm[player].y, enclosed);
  3307. // draw head
  3308. field[worm[player].x][worm[player].y] = FIRSTHEAD + player;
  3309. drawhead(player, x, y);
  3310.  
  3311. // protector collision detection
  3312. for (thisprot = 0; thisprot <= PROTECTORS; thisprot++)
  3313.     if (protector[player][thisprot].alive && protector[player][thisprot].visible)
  3314.     {    protcol(player, protector[player][thisprot].x, protector[player][thisprot].y, thisprot);
  3315.         // draw protector
  3316.                 if (protector[player][thisprot].alive && protector[player][thisprot].visible) // in case protector has just been killed, etc.
  3317.             change(protector[player][thisprot].x, protector[player][thisprot].y, FIRSTPROTECTOR + player);
  3318.     }
  3319.  
  3320. if (worm[player].cutter)
  3321. {   // straight ahead
  3322.     x = xwrap(worm[player].x + worm[player].deltax);
  3323.     y = ywrap(worm[player].y + worm[player].deltay);
  3324.     score += squareblast(HEAD, player, field[x][y], x, y, TRUE);
  3325.     // left
  3326.     if (!worm[player].deltax || !worm[player].deltay)
  3327.     {   // if orthagonal
  3328.         x = xwrap(worm[player].x + worm[player].deltay);
  3329.         y = ywrap(worm[player].y - worm[player].deltax);
  3330.     } else // diagonal
  3331.     {   if (worm[player].deltax == worm[player].deltay)
  3332.         {   x = xwrap(worm[player].x + worm[player].deltax);
  3333.             y = ywrap(worm[player].y - worm[player].deltay);
  3334.         } else
  3335.         {   x = xwrap(worm[player].x - worm[player].deltax);
  3336.             y = ywrap(worm[player].y + worm[player].deltay);
  3337.     }   }
  3338.     score += squareblast(HEAD, player, field[x][y], x, y, TRUE);
  3339.     // right
  3340.     if (!worm[player].deltax || !worm[player].deltay)
  3341.     {   // if orthagonal
  3342.         x = xwrap(worm[player].x - worm[player].deltay);
  3343.         y = ywrap(worm[player].y + worm[player].deltax);
  3344.     } else // diagonal
  3345.     {   if (worm[player].deltax == worm[player].deltay)
  3346.         {   x = xwrap(worm[player].x - worm[player].deltax);
  3347.             y = ywrap(worm[player].y + worm[player].deltay);
  3348.         } else
  3349.         {   x = xwrap(worm[player].x + worm[player].deltax);
  3350.             y = ywrap(worm[player].y - worm[player].deltay);
  3351.     }   }
  3352.     score += squareblast(HEAD, player, field[x][y], x, y, TRUE);
  3353.     // ahead left
  3354.     if (!worm[player].deltax || !worm[player].deltay)
  3355.     {   // if orthagonal
  3356.         if (worm[player].deltax) // if east or west
  3357.         {   x = xwrap(worm[player].x + worm[player].deltax);
  3358.             y = ywrap(worm[player].y - worm[player].deltax);
  3359.         } else // north or south
  3360.         {   x = xwrap(worm[player].x + worm[player].deltay);
  3361.             y = ywrap(worm[player].y + worm[player].deltay);
  3362.     }   }
  3363.     else // diagonal
  3364.     {   if (worm[player].deltax == worm[player].deltay)
  3365.         {   x = xwrap(worm[player].x + worm[player].deltax);
  3366.             y = worm[player].y;
  3367.         } else
  3368.         {   x = worm[player].x;
  3369.             y = ywrap(worm[player].y + worm[player].deltay);
  3370.     }   }
  3371.     score += squareblast(HEAD, player, field[x][y], x, y, TRUE);
  3372.     // ahead right
  3373.     if (!worm[player].deltax || !worm[player].deltay)
  3374.     {   // if orthagonal
  3375.         if (worm[player].deltax) // if east or west
  3376.         {   x = xwrap(worm[player].x + worm[player].deltax);;
  3377.             y = ywrap(worm[player].y + worm[player].deltax);
  3378.         } else // north or south
  3379.         {   x = xwrap(worm[player].x - worm[player].deltay);
  3380.             y = ywrap(worm[player].y + worm[player].deltay);
  3381.     }   }
  3382.     else // diagonal
  3383.     {   if (worm[player].deltax == worm[player].deltay)
  3384.         {   x = worm[player].x;
  3385.             y = ywrap(worm[player].y + worm[player].deltay);
  3386.         } else
  3387.         {   x = xwrap(worm[player].x + worm[player].deltax);
  3388.             y = worm[player].y;
  3389.     }   }
  3390.     score += squareblast(HEAD, player, field[x][y], x, y, TRUE);
  3391.     wormscore(player, score);
  3392. }
  3393. }
  3394.  
  3395. MODULE void protcol(SBYTE player, SBYTE x, SBYTE y, SBYTE thisprot)
  3396. {    UBYTE c = field[x][y];
  3397.     SBYTE i;
  3398.     ULONG score = 0;
  3399.  
  3400.         if (c >= FIRSTHEAD && c <= LASTHEAD)
  3401.             protworm(x, y, player, c - FIRSTHEAD);
  3402.         elif (c >= FIRSTTAIL && c <= LASTTAIL)
  3403.         {   if (player == c - FIRSTTAIL || worm[player].mode == TONGUE)
  3404.                 protector[player][thisprot].visible = FALSE;
  3405.         } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  3406.             protprot(x, y, player, c - FIRSTPROTECTOR);
  3407.         elif (c == STONE || c == WOOD || c == METAL || c == TIMEBOMB || c == TELEPORT)
  3408.             protector[player][thisprot].visible = FALSE;
  3409.         elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  3410.         {   i = whichcreature(x, y, MISSILE, 255);
  3411.             protmissile(x, y, player, i);
  3412.         } elif (c == WHIRLWIND)
  3413.         {   i = whichcreature(x, y, WHIRLWIND, 255);
  3414.             protwhirlwind(x, y, player, i);
  3415.         } elif (c == DOG)
  3416.         {   i = whichcreature(x, y, DOG, 255);
  3417.             protdog(x, y, player, i);
  3418.         } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  3419.         {   i = whichcreature(x, y, DRIP, 255);
  3420.             protdrip(x, y, player, i);
  3421.         } elif (c == PENGUIN)
  3422.         {   i = whichcreature(x, y, PENGUIN, 255);
  3423.             protpenguin(x, y, player, i);
  3424.         } elif (c == ORB)
  3425.         {   i = whichcreature(x, y, ORB, 255);
  3426.             protorb(x, y, player, i);
  3427.         } elif (c == FRAGMENT)
  3428.         {   i = whichcreature(x, y, FRAGMENT, 255);
  3429.             protfrag(x, y, player, i);
  3430.         } elif (c == CLOUD)
  3431.         {   i = whichcreature(x, y, CLOUD, 255);
  3432.             cloudprot(x, y, i, player);
  3433.         } elif (c == FIRSTFIRE + player)
  3434.             protector[player][thisprot].visible = FALSE;
  3435.         elif (c == GOAT)
  3436.         {   effect(FXUSE_PROTECTOR);
  3437.             effect(FXDEATH_GOAT);
  3438.             creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  3439.             protector[player][thisprot].last = BONUS;
  3440.             score += KILLGOAT;
  3441.             if (worm[player].bias)
  3442.             {   worm[player].lives += GOATBLOOD;
  3443.                 stat(player, LIFE);
  3444.         }   }
  3445.         else bothcol(player, x, y);
  3446.     wormscore(player, score);
  3447. }
  3448.  
  3449. MODULE void bothcol(SBYTE player, SBYTE x, SBYTE y)
  3450. {   UBYTE c = field[x][y];
  3451.     SBYTE i, j;
  3452.     ULONG score = 0;
  3453.  
  3454.     if (c >= FIRSTLETTER && c <= LASTLETTER)
  3455.     {   wormletter(player, c);
  3456.         putletter(player);
  3457.     } elif (c <= LASTOBJECT)
  3458.     {   score += wormobject(player, x, y);
  3459.     } else
  3460.     {   switch(c)
  3461.         {
  3462.         case EMPTY:
  3463.             score += EMPTYPOINT;
  3464.         break;
  3465.         case SILVER:
  3466.             score += SILVERPOINT;
  3467.         break;
  3468.         case GOLD:
  3469.             score += GOLDPOINT;
  3470.         break;
  3471.         case SKULL:
  3472.             effect(FXGET_SKULL);
  3473.             score += SKULLPOINT;
  3474.             j = -1; // for safety
  3475.             for (i = 0; i <= 3; i++)
  3476.             {   if (!worm[i].lives && x == worm[i].x && y == worm[i].y && worm[i].control != NONE)
  3477.                     j = i;
  3478.             }
  3479.             if (j != -1)
  3480.             {   worm[player].bias += worm[j].bias;
  3481.                 if (worm[player].bias > 0)
  3482.                 {   if (worm[player].armour > BIASLIMIT)
  3483.                         worm[player].armour = BIASLIMIT;
  3484.                     stat(player, BIAS);
  3485.                     worm[j].bias = 0;
  3486.                     stat(j, BIAS);
  3487.                 }
  3488.                 worm[player].multi *= worm[j].multi;
  3489.                 if (worm[player].multi > 1)
  3490.                 {   if (worm[player].multi > MULTILIMIT)
  3491.                         worm[player].multi = MULTILIMIT;
  3492.                 }
  3493.                 worm[player].power += worm[j].power;
  3494.                 if (worm[player].power > 1)
  3495.                 {   if (worm[player].power > POWERLIMIT)
  3496.                         worm[player].power = POWERLIMIT;
  3497.                     stat(player, POWER);
  3498.                     worm[j].power = 0;
  3499.                     stat(j, POWER);
  3500.                 }
  3501.                 worm[player].ammo += worm[j].ammo;
  3502.                 if (worm[player].ammo > 0)
  3503.                 {   if (worm[player].ammo > AMMOLIMIT)
  3504.                         worm[player].ammo = AMMOLIMIT;
  3505.                     stat(player, AMMO);
  3506.                     worm[j].ammo = 0;
  3507.                     stat(j, AMMO);
  3508.                 }
  3509.                 worm[player].armour += worm[j].armour;
  3510.                 if (worm[player].armour > 0)
  3511.                 {   if (worm[player].armour > MODELIMIT)
  3512.                         worm[player].armour = MODELIMIT;
  3513.                     stat(player, ARMOUR);
  3514.                     worm[j].armour = 0;
  3515.                     stat(j, ARMOUR);
  3516.                 }
  3517.                 worm[player].tongue += worm[j].tongue;
  3518.                 if (worm[player].tongue > 0)
  3519.                 {   if (worm[player].armour > MODELIMIT)
  3520.                         worm[player].armour = MODELIMIT;
  3521.                     stat(player, TONGUE);
  3522.                     worm[j].tongue = 0;
  3523.                     stat(j, TONGUE);
  3524.                 }
  3525.                 if (worm[player].armour > 0 || worm[player].tongue > 0)
  3526.                 {   if (worm[player].armour >= worm[player].tongue)
  3527.                         worm[player].mode = ARMOUR;
  3528.                     else worm[player].mode = TONGUE;
  3529.                 }
  3530.                 if (worm[j].nitro)
  3531.                 {   worm[player].nitro = TRUE;
  3532.                     stat(player, NITRO);
  3533.                     worm[j].nitro = FALSE;
  3534.                     worm[j].speed = NORMAL;
  3535.                     stat(j, NITRO);
  3536.                 }
  3537.                 if (worm[j].affixer)
  3538.                 {   worm[player].affixer = TRUE;
  3539.                     icon(player, AFFIXER);
  3540.                     worm[j].affixer = FALSE;
  3541.                     icon(j, AFFIXER);
  3542.                 }
  3543.                 if (worm[j].remnants)
  3544.                 {   worm[player].remnants = TRUE;
  3545.                     icon(player, REMNANTS);
  3546.                     worm[j].remnants = FALSE;
  3547.                     icon(j, REMNANTS);
  3548.                 }
  3549.                 if (worm[j].sideshot)
  3550.                 {   worm[player].sideshot = TRUE;
  3551.                     icon(player, SIDESHOT);
  3552.                     worm[j].sideshot = FALSE;
  3553.                     icon(j, SIDESHOT);
  3554.                 }
  3555.                 if (worm[j].pusher)
  3556.                 {   worm[player].pusher = TRUE;
  3557.                     icon(player, PUSHER);
  3558.                     worm[j].pusher = FALSE;
  3559.                     icon(j, PUSHER);
  3560.                 }
  3561.                 if (worm[j].cutter)
  3562.                 {   worm[player].cutter += worm[j].cutter;
  3563.                     icon(player, CUTTER);
  3564.                     worm[j].cutter = 0;
  3565.                     icon(j, CUTTER);
  3566.                 }
  3567.                 for (i = 0; i <= LETTERS; i++)
  3568.                     if (letters[j][i])
  3569.                     {   drawletter(j, FIRSTLETTER + i, BLACK);
  3570.                         if (!letters[player][i])
  3571.                         {   letters[player][i] = TRUE;
  3572.                             drawletter(player, FIRSTLETTER + i, NORMAL);
  3573.                     }   }
  3574.             } else ; // assert(0);
  3575.         break;
  3576.         default:
  3577.         break;
  3578.     }   } 
  3579.     wormscore(player, score);
  3580. }
  3581.  
  3582. void wormscore(SBYTE player, LONG score)
  3583. {   worm[player].score += score * worm[player].multi * players;
  3584.     stat(player, BONUS);
  3585. }
  3586.  
  3587. MODULE SWORD wsign(SWORD value)
  3588. {    if (value < 0)
  3589.         return (-1);
  3590.     elif (value > 0)
  3591.         return (1);
  3592.     else
  3593.         return (0);
  3594. }
  3595.  
  3596. SBYTE xwrap(SBYTE x)
  3597. {    if (x < 0)
  3598.         x += FIELDX + 1;
  3599.     elif (x > FIELDX)
  3600.         x -= FIELDX + 1;
  3601.     return(x);
  3602. }
  3603. SBYTE ywrap(SBYTE y)
  3604. {    if (y < 0)
  3605.         y += FIELDY + 1;
  3606.     elif (y > FIELDY)
  3607.         y -= FIELDY + 1;
  3608.     return(y);
  3609. }
  3610.  
  3611. MODULE void ramming(SBYTE player)
  3612. {   SBYTE i;
  3613.  
  3614.     worm[player].rammed = TRUE;
  3615.     worm[player].x = xwrap(worm[player].x - worm[player].deltax);
  3616.     worm[player].y = ywrap(worm[player].y - worm[player].deltay);
  3617.     for (i = 0; i <= PROTECTORS; i++)
  3618.     {   /* no point checking whether the protectors are alive or dead */
  3619.         protector[player][i].x -= worm[player].deltax;
  3620.         protector[player][i].y -= worm[player].deltay;
  3621. }   }
  3622.  
  3623. MODULE SWORD atleast(SWORD value, SWORD minimum)
  3624. {    if (value < minimum)
  3625.         return(minimum);
  3626.     else return(value);
  3627. }
  3628.  
  3629. MODULE void orbscore(SBYTE which, ULONG score)
  3630. {   creature[which].score += score * creature[which].multi;
  3631. }
  3632.  
  3633. MODULE void __inline change(SBYTE x, SBYTE y, UBYTE image)
  3634. {   // assert(valid(x, y));
  3635.     field[x][y] = image;
  3636.     draw(x, y, image);
  3637. }
  3638.  
  3639. MODULE void createmissile(UBYTE player, SBYTE x, SBYTE y)
  3640. {   UBYTE i;
  3641.  
  3642.     for (i = 0; i <= CREATURES; i++)
  3643.         if (!creature[i].alive)
  3644.         {   effect(FXBORN_MISSILE);
  3645.             creature[i].alive      = TRUE;
  3646.             creature[i].x          = x;
  3647.             creature[i].y          = y;
  3648.             creature[i].species    = MISSILE;
  3649.             creature[i].type       = player;
  3650.             creature[i].last       = EMPTY;
  3651.             creature[i].visible    = FALSE;
  3652.             if (level)
  3653.                 creature[i].speed  = (SBYTE) atleast(MISSILESPEED - (level / 2), 1);
  3654.             else creature[i].speed = BONUSMISSILESPEED;
  3655.             break;
  3656. }       }
  3657.  
  3658. /* WormWars FSET format for fieldset contents and high score table (Amiga
  3659. and IBM-PC), as follows:
  3660.  
  3661. header
  3662.         TEXT[]                          "FSET x.x" (NULL-terminated)
  3663.     SBYTE                levels;
  3664. high score table
  3665.     for (slot = 0; slot <= HISCORES; slot++)
  3666.     {    SBYTE            hiscore[slot].player,
  3667.                     hiscore[slot].level;
  3668.         SLONG            hiscore[slot].score;
  3669.         TEXT[]            hiscore[slot].name (NULL-terminated)
  3670.         TEXT[]            hiscore[slot].time (NULL-terminated)
  3671.         TEXT[]            hiscore[slot].date (NULL-terminated)
  3672.     }
  3673. level data
  3674.     for (level = 0; level <= levels; level++)
  3675.     {    SBYTE            startx[level],
  3676.                         starty[level];
  3677.         ABOOL            teleport[level][0].alive;
  3678.         SBYTE            teleport[level][0].x,
  3679.                         teleport[level][0].y;
  3680.         ABOOL            teleport[level][1].alive;
  3681.         SBYTE            teleport[level][1].x,
  3682.                         teleport[level][1].y;
  3683.         for (x = 0; x <= FIELDX; x++)
  3684.             for (y = 0; y <= FIELDY; y++)
  3685.                 SBYTE    board[level][x][y];
  3686.     }
  3687. version string
  3688.         TEXT[]                          "$VER: Worm Wars x.x (dd.mm.yy) $" (NULL-terminated) */
  3689.  
  3690. MODULE SBYTE onlyworm(ABOOL alive)
  3691. {   UBYTE i, theworm, worms = 0;
  3692.  
  3693.     for (i = 0; i <= 3; i++)
  3694.         if (worm[i].control != NONE && ((!alive) || worm[i].lives))
  3695.         {   theworm = i;
  3696.             worms++;
  3697.         }
  3698.     if (worms == 1)
  3699.         return (SBYTE) theworm;
  3700.     else return -1;
  3701. }
  3702.  
  3703. /* cloud, prot, worm, dog, drip, frag, missile, orb, penguin, whirlwind
  3704.  
  3705. Whichever is earlier in that list comes earlier in the function name. For
  3706. example, frag-orb and orb-frag collisions both use fragorb(): there is no
  3707. such routine as orbfrag(). Also, there are no such routines as dripdrip()
  3708. and penguinpenguin(). */
  3709.  
  3710. MODULE void dogdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3711. {   creature[which1].alive = FALSE;
  3712.     creature[which2].alive = FALSE;
  3713.     change(x, y, LIFE);
  3714. }
  3715. MODULE void dogdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3716. {   creature[which1].alive = FALSE;
  3717. }
  3718. MODULE void dogfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3719. {   creature[which1].alive = FALSE;
  3720.     creature[which2].alive = FALSE;
  3721.     change(x, y, BONUS);
  3722. }
  3723. MODULE void dogmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3724. {   creature[which1].alive = FALSE;
  3725.     creature[which2].alive = FALSE;
  3726.     change(x, y, BONUS);
  3727. }
  3728. MODULE void dogorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3729. {   creature[which1].alive = FALSE;
  3730. }
  3731. MODULE void dogpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3732. {   creature[which2].alive = FALSE;
  3733. }
  3734. MODULE void dogwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3735. {   creature[which1].alive = FALSE;
  3736. }
  3737. MODULE void dripfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3738. {   creature[which1].alive = FALSE;
  3739.     creature[which2].alive = FALSE;
  3740.     change(x, y, BONUS);
  3741. }
  3742. MODULE void dripmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3743. {   /* drip lives, missile dies */
  3744.     creature[which2].alive = FALSE;
  3745. }
  3746. MODULE void driporb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3747. {   creature[which1].alive = FALSE;
  3748.     if (creature[which2].mode != ARMOUR)
  3749.     {   creature[which2].explode = TRUE;
  3750.         draw(x, y, EMPTY);
  3751. }   }
  3752. MODULE void drippenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3753. {   creature[which2].alive = FALSE;
  3754. }
  3755. MODULE void dripwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3756. {   creature[which1].alive = FALSE;
  3757. }
  3758. MODULE void fragfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3759. {   effect(FXDEATH_FRAGMENT);
  3760.     creature[which1].alive = FALSE;
  3761.     creature[which2].alive = FALSE;
  3762.     draw(x, y, EMPTY);
  3763. }
  3764. MODULE void fragmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3765. {   creature[which1].alive = FALSE;
  3766.     creature[which2].alive = FALSE;
  3767.     change(x, y, EMPTY);
  3768. }
  3769. MODULE void fragorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3770. {   creature[which1].alive = FALSE;
  3771.     if (creature[which2].mode != ARMOUR)
  3772.     {   creature[which2].explode = TRUE;
  3773.         draw(x, y, EMPTY);
  3774.     } else effect(FXUSE_ARMOUR);
  3775. }
  3776. MODULE void fragpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3777. {   creature[which2].alive = FALSE;
  3778. }
  3779. MODULE void fragwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3780. {   creature[which1].alive = FALSE;
  3781. }
  3782. MODULE void missilemissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3783. {   creature[which1].alive = FALSE;
  3784.     creature[which2].alive = FALSE;
  3785.     change(x, y, BONUS);
  3786. }
  3787. MODULE void missilepenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3788. {   creature[which2].alive = FALSE;
  3789. }
  3790. MODULE void missilewhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3791. {   creature[which1].alive = FALSE;
  3792. }
  3793. MODULE void orborb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3794. {   effect(FXDEATH_ORB);
  3795.     creature[which1].alive = FALSE;
  3796.     creature[which2].alive = FALSE;
  3797.     change(x, y, BONUS);
  3798. }
  3799. MODULE void orbmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3800. {   if (creature[which1].mode != ARMOUR)
  3801.     {   effect(FXDEATH_ORB);
  3802.         creature[which1].alive = FALSE;
  3803.         creature[which2].alive = FALSE;
  3804.         change(x, y, BONUS);
  3805.         wormscore(creature[which2].type, creature[which1].score);
  3806.         if (worm[creature[which2].type].bias)
  3807.         {   worm[creature[which2].type].lives += ORBBLOOD;
  3808.             stat(creature[which2].type, LIFE);
  3809.     }   }
  3810.     else effect(FXUSE_ARMOUR);
  3811. }
  3812. MODULE void orbpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3813. {   creature[which2].alive = FALSE;
  3814.     if (creature[which1].mode == ARMOUR)
  3815.         orbscore(which1, KILLPENGUIN);
  3816.     else
  3817.     {   creature[which1].alive = FALSE;
  3818.         change(x, y, BONUS);
  3819. }   }
  3820. MODULE void orbwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3821. {   creature[which1].alive = FALSE;
  3822. }
  3823. MODULE void penguinwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3824. {   creature[which1].alive = FALSE;
  3825. }
  3826. MODULE void whirlwindwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3827. {   creature[which1].alive = FALSE;
  3828.     creature[which2].alive = FALSE;
  3829.     change(x, y, LIFE);
  3830. }
  3831. MODULE void wormdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3832. {   if (creature[which2].dormant == DORMANT)
  3833.     {   effect(FXBORN_DOG);
  3834.         creature[which2].dormant = AWAKENING;
  3835.         creature[which2].type = which1;
  3836.         worm[which1].last = DOG;
  3837.     } else
  3838.     {   creature[which2].alive = FALSE;
  3839.         if (worm[which1].mode != ARMOUR)
  3840.         {   worm[which1].alive = FALSE;
  3841.             worm[which1].cause = DOG;
  3842.             worm[which1].victor = -1;
  3843. }   }   }
  3844. MODULE void wormdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3845. {   creature[which2].alive = FALSE;
  3846.     if (which1 == creature[which2].type)
  3847.     {   effect(FXGET_DRIP);
  3848.         wormscore(which1, DRIPBONUS);
  3849.         if (worm[which1].bias)
  3850.         {    worm[which1].lives += DRIPBLOOD;
  3851.             stat(which1, LIFE);
  3852.     }    }
  3853.     else
  3854.     {    worm[which1].alive = FALSE;
  3855.         worm[which1].cause = FIRSTDRIP + creature[which2].type;
  3856.         worm[which1].victor = -1;
  3857. }   }
  3858. MODULE void wormfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3859. {   if (worm[which1].mode != ARMOUR)
  3860.     {    worm[which1].cause = FRAGMENT;
  3861.     worm[which1].victor = -1;
  3862.     worm[which1].alive = FALSE;
  3863.         creature[which2].alive = FALSE;
  3864.     } else
  3865.     {   effect(FXUSE_ARMOUR);
  3866.     reflect(which2);
  3867. }   }
  3868. MODULE void wormmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3869. {   if (creature[which2].type == which1)
  3870.         creature[which2].visible = FALSE;
  3871.     else
  3872.     {   creature[which2].alive = FALSE;
  3873.     if (worm[which1].mode != ARMOUR)
  3874.     {   worm[which1].cause = FIRSTMISSILE + creature[which2].type;
  3875.               worm[which1].victor = creature[which2].type;
  3876.               worm[which1].alive = FALSE;
  3877.         } else effect(FXUSE_ARMOUR);
  3878. }   }
  3879. MODULE void wormorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3880. {   if (worm[which1].mode == ARMOUR)
  3881.     {   effect(FXUSE_ARMOUR);
  3882.         effect(FXDEATH_ORB);
  3883.         wormscore(which1, creature[which2].score);
  3884.         creature[which2].alive = FALSE;
  3885.         if (worm[which1].bias)
  3886.         {   worm[which1].lives += ORBBLOOD;
  3887.             stat(which1, LIFE);
  3888.     }   }
  3889.     else
  3890.     {   if (creature[which2].mode == ARMOUR)
  3891.         {   effect(FXUSE_ARMOUR);
  3892.             orbscore(which2, KILLWORM);
  3893.         } else creature[which2].alive = FALSE;
  3894.     worm[which1].cause = ORB;
  3895.     worm[which1].victor = -1;
  3896.     worm[which1].alive = FALSE;
  3897. }   }
  3898. MODULE void wormpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3899. {   effect(FXDEATH_PENGUIN);
  3900.     creature[which2].alive = FALSE;
  3901.     if (worm[which1].armour)
  3902.     {   wormscore(which1, KILLPENGUIN);
  3903.     if (worm[which1].bias)
  3904.     {   worm[which1].lives += PENGUINBLOOD;
  3905.         stat(which1, LIFE);
  3906.     }   }
  3907.     else
  3908.     {   worm[which1].alive = FALSE;
  3909.         worm[which1].cause = PENGUIN;
  3910.         worm[which1].victor = -1;
  3911. }   }
  3912. MODULE void wormwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3913. {   worm[which1].cause = WHIRLWIND;
  3914.     worm[which1].victor = -1;
  3915.     worm[which1].alive = FALSE;
  3916. }
  3917. MODULE void wormworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3918. {   if (worm[which1].mode != TONGUE && worm[which2].mode != TONGUE)
  3919.     {   /* both worms die */
  3920.         worm[which1].cause  = FIRSTHEAD + which2;
  3921.         worm[which1].alive  = FALSE;
  3922.         worm[which1].victor = -1;
  3923.         worm[which2].cause  = FIRSTHEAD + which1;
  3924.         worm[which2].alive  = FALSE;
  3925.         worm[which2].victor = -1;
  3926.     } elif (worm[which1].mode == TONGUE && worm[which2].mode != TONGUE)
  3927.     {   /* 1st worm lives, 2nd worm dies  */
  3928.         worm[which2].cause  = FIRSTHEAD + which1;
  3929.         worm[which2].alive  = FALSE;
  3930.         worm[which2].victor = which1;
  3931.     } elif (worm[which1].mode != TONGUE && worm[which2].mode == TONGUE)
  3932.     {   /* 1st worm dies, 2nd worm lives */
  3933.         worm[which1].cause  = FIRSTHEAD + which2;
  3934.         worm[which1].alive  = FALSE;
  3935.         worm[which1].victor = which2;
  3936. }   }
  3937. MODULE void protdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3938. {   creature[which2].alive = FALSE;
  3939. }
  3940. MODULE void protdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3941. {   creature[which2].alive = FALSE;
  3942.     if (which1 == creature[which2].type)
  3943.     {   effect(FXGET_DRIP);
  3944.         wormscore(which1, DRIPBONUS);
  3945.         if (worm[which1].bias)
  3946.         {    worm[which1].lives += DRIPBLOOD;
  3947.             stat(which1, LIFE);
  3948.     }    }
  3949.     else effect(FXUSE_PROTECTOR);
  3950. }
  3951. MODULE void protfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3952. {   effect(FXUSE_PROTECTOR);
  3953.     reflect(which2);
  3954. }
  3955. MODULE void protmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3956. {   if (which1 != creature[which2].type)
  3957.     {   effect(FXUSE_PROTECTOR);
  3958.         creature[which2].alive = FALSE;
  3959.     } else creature[which2].visible = FALSE;
  3960. }
  3961. MODULE void protorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3962. {   effect(FXUSE_PROTECTOR);
  3963.     effect(FXDEATH_ORB);
  3964.     wormscore(which1, creature[which2].score);
  3965.     creature[which2].alive = FALSE;
  3966.     if (worm[which1].bias)
  3967.     {   worm[which1].lives += ORBBLOOD;
  3968.         stat(which1, LIFE);
  3969. }   }
  3970. MODULE void protpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3971. {   effect(FXUSE_PROTECTOR);
  3972.     effect(FXDEATH_PENGUIN);
  3973.     wormscore(which1, KILLPENGUIN);
  3974.     creature[which2].alive = FALSE;
  3975.     if (worm[which1].bias)
  3976.     {   worm[which1].lives += PENGUINBLOOD;
  3977.         stat(which1, LIFE);
  3978. }   }
  3979. MODULE void protwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3980. {   UBYTE i;
  3981.  
  3982.     for (i = 0; i <= PROTECTORS; i++)
  3983.          if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  3984.               protector[which1][i].alive = FALSE;    
  3985. }
  3986. MODULE void protworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3987. {   UBYTE i, j;
  3988.  
  3989.     for (i = 0; i <= PROTECTORS; i++)
  3990.          if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  3991.          {    j = i;
  3992.               break;
  3993.          }
  3994.  
  3995.     if (which1 != which2)
  3996.     {   if (worm[which2].mode != ARMOUR)
  3997.         {   effect(FXUSE_PROTECTOR);
  3998.             worm[which2].cause  = FIRSTPROTECTOR + which1;
  3999.             worm[which2].victor = which1;
  4000.             worm[which2].alive  = FALSE;
  4001.         } else
  4002.         {   effect(FXUSE_ARMOUR);
  4003.             protector[which1][j].visible = FALSE;
  4004.     }   }
  4005.     else
  4006.     {   /* protector is over worm's own head; caused by ramming */
  4007.         protector[which1][j].visible = FALSE;
  4008. }   }
  4009. MODULE void protprot(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4010. {   UBYTE i, p1, p2;
  4011.  
  4012.     /* Find both protectors */
  4013.  
  4014.     for (i = 0; i <= PROTECTORS; i++)
  4015.     {   if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  4016.             p1 = i;
  4017.         if (protector[which2][i].alive && protector[which2][i].x == x && protector[which2][i].y == y)
  4018.             p2 = i;
  4019.     }
  4020.     protector[which1][p1].alive = FALSE;
  4021.     protector[which2][p2].alive = FALSE;
  4022.     change(x, y, EMPTY);
  4023. }
  4024. MODULE void cloudcloud(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4025. {   creature[which1].alive = FALSE;
  4026.     creature[which2].alive = FALSE;
  4027.     change(x, y, LIGHTNING);
  4028. }
  4029. MODULE void clouddog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4030. {   creature[which2].alive = FALSE;
  4031. }
  4032. MODULE void clouddrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4033. {   creature[which2].alive = FALSE;
  4034. }
  4035. MODULE void cloudfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4036. {   creature[which1].alive = FALSE;
  4037. }
  4038. MODULE void cloudmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4039. {   creature[which2].alive = FALSE;
  4040. }
  4041. MODULE void cloudorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4042. {   creature[which1].alive = FALSE;
  4043. }
  4044. MODULE void cloudpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4045. {   creature[which2].alive = FALSE;
  4046. }
  4047. MODULE void cloudprot(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4048. {   creature[which1].alive = FALSE;
  4049. }
  4050. MODULE void cloudwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4051. {   creature[which1].alive = FALSE;
  4052. }
  4053. MODULE void cloudworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  4054. {   creature[which1].alive = FALSE;
  4055.     if (worm[which2].mode != ARMOUR)
  4056.     {   worm[which2].alive = FALSE;
  4057.         worm[which2].cause = CLOUD;
  4058.         worm[which2].victor = -1;
  4059. }   }
  4060.  
  4061. MODULE ULONG wormobject(UBYTE player, SBYTE x, SBYTE y)
  4062. {   AUTO    UBYTE c = field[x][y], d;
  4063.     AUTO    ULONG score = object[c].score;
  4064.     AUTO    UBYTE i, j;
  4065.     AUTO    SBYTE xx, xxx, yy, yyy;
  4066.     AUTO    ABOOL done;
  4067.     PERSIST SBYTE otherfield[FIELDX + 1][FIELDY + 1];
  4068.  
  4069.     for (i = 0; i <= MAGNETS; i++)
  4070.         if (magnet[i].alive && x == magnet[i].x && y == magnet[i].y)
  4071.              magnet[i].alive = FALSE;
  4072.  
  4073.     if (!valid(x, y)) // defensive programming
  4074.     {   return 0;
  4075.  
  4076.         /* AUTO TEXT temp1[SAYLIMIT + 1], temp2[8];
  4077.  
  4078.         strcpy(temp1, "BAD OBJECT AT x: ");
  4079.         stci_d(temp2, x);
  4080.         strcat(temp1, temp2);
  4081.         strcat(temp1, ", y: ");
  4082.         stci_d(temp2, y);
  4083.         strcat(temp1, temp2);
  4084.         strcat(temp1, "!");
  4085.         say(temp1, worm[player].colour);
  4086.         draw(FIELDX + 1, 0, c); // indicates which object
  4087.         Delay(250);
  4088.         clearkybd();
  4089.         anykey(FALSE); */
  4090.     }
  4091.  
  4092.     switch(c)
  4093.     {
  4094.     case BONUS:
  4095.         effect(FXGET_OBJECT);
  4096.         i = rand() % (LETTERS + 1);
  4097.         letters[player][i] = TRUE;
  4098.         drawletter(player, FIRSTLETTER + i, NORMAL);
  4099.     break;
  4100.     case AMMO:
  4101.         effect(FXGET_AMMO);
  4102.         worm[player].ammo += (rand() % 5) + 2; /* 2-6 bullets */
  4103.         stat(player, AMMO);
  4104.     break;
  4105.     case ARMOUR:
  4106.         effect(FXGET_OBJECT);
  4107.         worm[player].armour += MODEADD + (rand() % MODERAND);
  4108.         worm[player].mode = ARMOUR;
  4109.         stat(player, ARMOUR);
  4110.     break;
  4111.     case TONGUE:
  4112.         effect(FXGET_OBJECT);
  4113.         worm[player].tongue += MODEADD + (rand() % MODERAND);
  4114.         worm[player].mode = TONGUE;
  4115.         stat(player, TONGUE);
  4116.         worm[player].last = FIRSTTAIL + player;
  4117.         break;
  4118.     case NITRO:
  4119.         effect(FXGET_NITRO);
  4120.         worm[player].nitro = TRUE;
  4121.         stat(player, NITRO);
  4122.     break;
  4123.     case BOMB:
  4124.         if (worm[player].mode == NOMODE)
  4125.             draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4126.         else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4127.             bombblast(HEAD, player, worm[player].x, worm[player].y);
  4128.     break;
  4129.     case POWER:
  4130.         effect(FXGET_POWERUP);
  4131.         if (worm[player].power < POWERLIMIT)
  4132.         {   worm[player].power += 2;
  4133.             stat(player, POWER);
  4134.         }
  4135.     break;
  4136.     case SLAYER:
  4137.         for (i = 0; i <= CREATURES; i++)
  4138.             if (creature[i].alive)
  4139.             {   if (creature[i].species == ORB)
  4140.                 {   effect(FXDEATH_ORB);
  4141.                     score += creature[i].score;
  4142.                     creature[i].explode = TRUE;
  4143.                     if (worm[player].bias)
  4144.                         worm[player].lives += ORBBLOOD;
  4145.                 } elif (creature[i].species == GOAT)
  4146.                 {   effect(FXDEATH_GOAT);
  4147.                     creature[i].alive = FALSE;
  4148.                     score += KILLGOAT;
  4149.                     if (worm[player].bias)
  4150.                         worm[player].lives += GOATBLOOD;
  4151.                     change(creature[i].x, creature[i].y, BONUS);
  4152.                 } elif (creature[i].species == PENGUIN)
  4153.                 {   effect(FXDEATH_PENGUIN);
  4154.                     creature[i].alive = FALSE;
  4155.                     score += KILLPENGUIN;
  4156.                     if (worm[player].bias)
  4157.                         worm[player].lives += PENGUINBLOOD;
  4158.                     change(creature[i].x, creature[i].y, EMPTY);
  4159.                 } elif (creature[i].species == DRIP || creature[i].species == CLOUD || (creature[i].species == MISSILE && creature[i].type != player))
  4160.                 {   creature[i].alive = FALSE;
  4161.                     change(creature[i].x, creature[i].y, EMPTY);
  4162.             }   }
  4163.         for (i = 0; i <= 3; i++)
  4164.             if (player != i && worm[i].mode != ARMOUR)
  4165.             {   worm[i].alive = FALSE;
  4166.                 worm[i].cause = SLAYER;
  4167.                 worm[i].victor = player;
  4168.             }
  4169.         for (x = 0; x <= FIELDX; x++)
  4170.             for (y = 0; y <= FIELDY; y++)
  4171.                 if (field[x][y] == SLIME)
  4172.                     change(x, y, EMPTY);
  4173.         if (worm[player].bias)
  4174.             stat(player, LIFE); // we do it here once for efficiency
  4175.     break;
  4176.     case PROTECTOR:
  4177.         done = FALSE;
  4178.         for (i = 0; i <= PROTECTORS; i++)
  4179.             if (!protector[player][i].alive && !done)
  4180.             {   do
  4181.                 {   protector[player][i].relx = ((rand() % 2) * 2) - 1;
  4182.                     protector[player][i].rely = ((rand() % 2) * 2) - 1;
  4183.                     for (j = 0; j <= PROTECTORS; j++)
  4184.                         if (i == NOSE || !protector[player][j].alive || protector[player][j].x != xwrap(worm[player].x + protector[player][i].relx) || protector[player][j].y != ywrap(worm[player].y + protector[player][i].rely))
  4185.                         {   effect(FXBORN_PROTECTOR);
  4186.                             done = TRUE;
  4187.                             protector[player][i].alive = TRUE;
  4188.                             protector[player][i].visible = FALSE;
  4189.                             protector[player][i].last = EMPTY;
  4190.                             if (i == NOSE)
  4191.                                 worm[player].position = -1;
  4192.                         }
  4193.                 } while (!done);
  4194.             }
  4195.     break;
  4196.     case MISSILE:
  4197.         createmissile(player, worm[player].x, worm[player].y);
  4198.     break;
  4199.     case LIFE:
  4200.         effect(FXGET_OBJECT);
  4201.         worm[player].lives += (rand() % 5) + 2; /* 2-6 lives */
  4202.         stat(player, LIFE);
  4203.     break;
  4204.     case MULTIPLIER:
  4205.         effect(FXGET_OBJECT);
  4206.         if (worm[player].multi < MULTILIMIT)
  4207.             worm[player].multi *= 2;
  4208.     break;
  4209.     case BIAS:
  4210.         effect(FXGET_OBJECT);
  4211.         worm[player].bias += MODEADD + (rand() % MODERAND);
  4212.         stat(player, BIAS);
  4213.     break;
  4214.     case ICE:
  4215.         effect(FXGET_OBJECT);
  4216.         worm[player].ice += ICEADD + (rand() % ICERAND);
  4217.         ice = player;
  4218.         icon(player, ICE);
  4219.     break;
  4220.     case GROWER:
  4221.         effect(FXGET_GROWER);
  4222.         /* grow silver */
  4223.         for (x = 0; x <= FIELDX; x++)
  4224.             for (y = 0; y <= FIELDY; y++)
  4225.                 if (field[x][y] == SILVER)
  4226.                     for (xx = x - 1; xx <= x + 1; xx++)
  4227.                         for (yy = y - 1; yy <= y + 1; yy++)
  4228.                             if (valid(xx, yy))
  4229.                                 if (field[xx][yy] == EMPTY || field[xx][yy] == TEMPTAIL)
  4230.                                     field[xx][yy] = TEMPSILVER;
  4231.         /* grow gold */
  4232.         for (x = 0; x <= FIELDX; x++)
  4233.             for (y = 0; y <= FIELDY; y++)
  4234.                 if (field[x][y] == GOLD)
  4235.                     for (xx = x - 1; xx <= x + 1; xx++)
  4236.                         for (yy = y - 1; yy <= y + 1; yy++)
  4237.                             if (valid(xx, yy))
  4238.                                 if (field[xx][yy] == EMPTY || field[xx][yy] == TEMPTAIL || field[xx][yy] == TEMPSILVER)
  4239.                                     field[xx][yy] = TEMPGOLD;
  4240.         /* update field */
  4241.         for (x = 0; x <= FIELDX; x++)
  4242.             for (y = 0; y <= FIELDY; y++)
  4243.                 switch (field[x][y])
  4244.                 {
  4245.                 case TEMPGOLD:
  4246.                     change(x, y, GOLD);
  4247.                 break;
  4248.                 case TEMPSILVER:
  4249.                     change(x, y, SILVER);
  4250.                 break;
  4251.                 case TEMPTAIL:
  4252.                     change(x, y, FIRSTTAIL + player);
  4253.                 break;
  4254.                 default:
  4255.                 break;
  4256.                 }
  4257.     break;
  4258.     case TREASURE:
  4259.         treasurer = player;
  4260.         if (level)
  4261.         {   secondsperlevel = 0;
  4262.             leveltype = rand() % 3;
  4263.             if (leveltype == 0)
  4264.             {   say("Bonus Level: Treasury!", worm[treasurer].colour);
  4265.                 leveltype = TREASURE;
  4266.             } elif (leveltype == 1)
  4267.             {   say("Bonus Level: Drips!", worm[treasurer].colour);
  4268.                 leveltype = DRIP;
  4269.             } else
  4270.             {   // assert(leveltype == 2);
  4271.                 say("Bonus Level: Penguins!", worm[treasurer].colour);
  4272.                 leveltype = PENGUIN;
  4273.         }   }
  4274.         secondsperlevel += TREASUREADD + (rand() % TREASURERAND);
  4275.         if (level && leveltype != TREASURE)
  4276.             secondsperlevel *= 2;
  4277.         if (secondsperlevel > TIMELIMIT)
  4278.             secondsperlevel = TIMELIMIT;
  4279.         if (level)
  4280.         {   stat(player, BONUS);
  4281.             reallevel = level;
  4282.             level = 0;
  4283.             newlevel(player);
  4284.         }
  4285.     break;
  4286.     case AFFIXER:
  4287.         effect(FXGET_OBJECT);
  4288.         worm[player].affixer = TRUE;
  4289.         icon(player, AFFIXER);
  4290.     break;
  4291.     case SWITCHER:
  4292.         effect(FXGET_OBJECT);
  4293.         if (players >= 2)
  4294.             for (x = 0; x <= FIELDX; x++)
  4295.                 for (y = 0; y <= FIELDY; y++)
  4296.                     if (field[x][y] >= FIRSTTAIL && field[x][y] <= LASTTAIL && field[x][y] != FIRSTTAIL + player)
  4297.                         change(x, y, FIRSTTAIL + player);
  4298.                     elif (worm[player].bias && field[x][y] >= FIRSTFIRE && field[x][y] <= LASTFIRE && field[x][y] != FIRSTFIRE + player)
  4299.                         change(x, y, FIRSTFIRE + player);
  4300.     break;
  4301.     case HEALER:
  4302.         effect(FXGET_OBJECT);
  4303.         if (worm[player].lives < 100)
  4304.             worm[player].lives = 100;
  4305.         else worm[player].lives = LIVESLIMIT;
  4306.         stat(player, LIFE);
  4307.     break;
  4308.     case UMBRELLA:
  4309.         level += (rand() % 2) + 1;
  4310.         if (level >= levels)
  4311.             level = levels; // fixed?
  4312.         for (i = 0; i <= LETTERS; i++)
  4313.             letters[player][i] = TRUE;
  4314.     break;
  4315.     case CLOCK:
  4316.         effect(FXGET_OBJECT);
  4317.         if (secondsleft)
  4318.         {   secondsperlevel += (rand() % CLOCKRAND) + CLOCKADD;
  4319.             if (secondsperlevel > TIMELIMIT)
  4320.                 secondsperlevel = TIMELIMIT;
  4321.         }
  4322.     break;
  4323.     case SLOWER:
  4324.         effect(FXGET_OBJECT);
  4325.         for (i = 0; i <= CREATURES; i++)
  4326.             if (creature[i].alive && creature[i].species != MISSILE)
  4327.                 creature[i].speed = (SBYTE) atleast(creature[i].speed * 2, VERYFAST);
  4328.     break;
  4329.     case PULSE:
  4330.         explosion(xwrap(worm[player].x - worm[player].deltax),
  4331.                   ywrap(worm[player].y - worm[player].deltay),
  4332.                                          worm[player].deltax,
  4333.                                          worm[player].deltay
  4334.                  );
  4335.     break;
  4336.     case REMNANTS:
  4337.         effect(FXGET_OBJECT);
  4338.         worm[player].remnants = TRUE;
  4339.         icon(player, REMNANTS);
  4340.     break;
  4341.     case SIDESHOT:
  4342.         effect(FXGET_POWERUP);
  4343.         worm[player].sideshot = TRUE;
  4344.         icon(player, SIDESHOT);
  4345.     break;
  4346.     case MAGNET:
  4347.         effect(FXGET_OBJECT);
  4348.         i = 0;
  4349.         field[x][y] = EMPTY; // so that the magnet itself is destroyed
  4350.         for (xx = 0; xx <= FIELDX; xx++)
  4351.             for (yy = 0; yy <= FIELDY; yy++)
  4352.                 if (field[xx][yy] <= LASTOBJECT)
  4353.                 {   while (magnet[i].alive && i < MAGNETS)
  4354.                        i++;
  4355.                     if (i > MAGNETS)
  4356.                     {   break;
  4357.                     } else
  4358.                     {   magnet[i].x      = xx;
  4359.                         magnet[i].y      = yy;
  4360.                         magnet[i].object = field[xx][yy];
  4361.                         magnet[i].player = player;
  4362.                         magnet[i].alive  = TRUE;
  4363.                         i++;
  4364.                 }   }
  4365.     break;
  4366.     case CUTTER:
  4367.         effect(FXGET_OBJECT);
  4368.         worm[player].cutter += (rand() % CUTTERRAND) + CUTTERADD;
  4369.          icon(player, CUTTER);
  4370.     break;
  4371.     case CYCLONE:
  4372.         /* create cyclones */
  4373.         for (i = 0; i <= CREATURES; i++)
  4374.             if (!(creature[i].alive))
  4375.             {   effect(FXGET_CYCLONE);
  4376.                 done = FALSE;
  4377.                 while (!done)
  4378.                 {   creature[i].x = rand() % (FIELDX + 1);
  4379.                     creature[i].y = (rand() % (FIELDY - 2)) + 3;
  4380.                     d = field[creature[i].x][creature[i].y];
  4381.                     if ((d >= FIRSTEMPTY && d <= LASTEMPTY) || (d >= FIRSTTAIL && d <= LASTTAIL))
  4382.                         done = TRUE;
  4383.                     /* Theoretically, this loop could hang... */
  4384.                 }
  4385.                 creature[i].last = EMPTY;
  4386.                 creature[i].speed = VERYFAST;
  4387.                 creature[i].visible = TRUE;
  4388.                 creature[i].deltax = 0;
  4389.                 creature[i].deltay = 0;
  4390.                 creature[i].species = WHIRLWIND;
  4391.                 creature[i].alive = TRUE;
  4392.                 change(creature[i].x, creature[i].y, WHIRLWIND);
  4393.                 break;
  4394.             }
  4395.     break;
  4396.     case LIGHTNING:
  4397.         effect(FXGET_OBJECT);
  4398.         for (xx = 0; xx <= FIELDX; xx++)
  4399.             for (yy = 0; yy <= FIELDY; yy++)
  4400.                 otherfield[xx][yy] = EMPTY;
  4401.         for (xx = 0; xx <= FIELDX; xx++)
  4402.             for (yy = 0; yy <= FIELDY; yy++)
  4403.                 if (field[xx][yy] == FIRSTTAIL + player)
  4404.                     for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  4405.                         for (yyy = yy - 1; yyy <= yy + 1; yyy++)
  4406.                             if (valid(xxx, yyy))
  4407.                             {   d = field[xxx][yyy];
  4408.                                 if (d == ORB
  4409.                                  || d == GOAT
  4410.                                  || d == MISSILE
  4411.                                  || d == PENGUIN
  4412.                                  || d == FRAGMENT
  4413.                                  || (d >= FIRSTTAIL && d <= LASTTAIL && d != FIRSTTAIL + player)
  4414.                                  || (d >= FIRSTHEAD && d <= LASTHEAD)
  4415.                                  || (d >= FIRSTDRIP && d <= LASTDRIP)
  4416.                                  || d <= LASTOBJECT)
  4417.                                 {   otherfield[xxx][yyy] = TEMPLIGHTNING;
  4418.                                     draw(xxx, yyy, LIGHTNING);
  4419.                             }   }
  4420.         for (xx = 0; xx <= FIELDX; xx++)
  4421.         {   for (yy = 0; yy <= FIELDY; yy++)
  4422.             {   if (otherfield[xx][yy] == TEMPLIGHTNING)
  4423.                 {   d = field[xx][yy];
  4424.                     switch(d)
  4425.                     {
  4426.                     case ORB:
  4427.                         i = whichcreature(xx, yy, ORB, 255);
  4428.                         if (creature[i].mode == ARMOUR)
  4429.                             draw(xx, yy, ORBARMOUR);
  4430.                         else
  4431.                         {   creature[i].alive = FALSE;
  4432.                             score += creature[i].score;
  4433.                             change(xx, yy, BONUS);
  4434.                         }
  4435.                     break;
  4436.                     case GOAT:
  4437.                         creature[whichcreature(xx, yy, GOAT, 255)].alive = FALSE;
  4438.                         score += KILLGOAT;
  4439.                         change(xx, yy, BONUS);
  4440.                     break;
  4441.                     case MISSILE:
  4442.                         i = whichcreature(xx, yy, MISSILE, 255);
  4443.                         if (player != creature[i].type)
  4444.                         {   creature[i].alive = FALSE;
  4445.                             change(xx, yy, EMPTY);
  4446.                         } else draw(xx, yy, FIRSTMISSILE + player);
  4447.                     break;
  4448.                     case PENGUIN:
  4449.                         score += KILLPENGUIN;
  4450.                     // note no break here
  4451.                     case FRAGMENT:
  4452.                         creature[whichcreature(xx, yy, d, 255)].alive = FALSE;
  4453.                         change(xx, yy, EMPTY);
  4454.                     break;
  4455.                     default:
  4456.                         if (d >= FIRSTDRIP && d <= LASTDRIP)
  4457.                         {   creature[whichcreature(xx, yy, DRIP, 255)].alive = FALSE;
  4458.                             score += DRIPBONUS;
  4459.                             if (player == d - FIRSTDRIP && worm[player].bias)
  4460.                             {    worm[player].lives += DRIPBLOOD;
  4461.                                 stat(player, LIFE);
  4462.                         }    }
  4463.                         elif (d >= FIRSTHEAD && d <= LASTHEAD)
  4464.                         {   if (player != d - FIRSTHEAD && worm[d - FIRSTHEAD].mode != ARMOUR)
  4465.                             {   worm[d - FIRSTHEAD].alive = FALSE;
  4466.                                 worm[d - FIRSTHEAD].cause = LIGHTNING;
  4467.                                 worm[d - FIRSTHEAD].victor = player;
  4468.                                 change(xx, yy, EMPTY);
  4469.                         }   }
  4470.                         else /* eg. tail */
  4471.                             change(xx, yy, EMPTY);
  4472.                     break;
  4473.         }   }   }   }
  4474.     break;
  4475.     case PUSHER:
  4476.         effect(FXGET_OBJECT);
  4477.         worm[player].pusher = TRUE;
  4478.         icon(player, PUSHER);
  4479.     break;
  4480.     case FREEDOM:
  4481.         effect(FXGET_OBJECT);
  4482.         worm[player].freedom += FREEDOMADD + (rand() % FREEDOMRAND);
  4483.         if (worm[player].freedom > FREEDOMLIMIT)
  4484.             worm[player].freedom = FREEDOMLIMIT;
  4485.         icon(player, FREEDOM);
  4486.     break;
  4487.     case CONVERTER:
  4488.         effect(FXGET_OBJECT);
  4489.         for (i = 0; i <= CREATURES; i++)
  4490.             if (creature[i].alive && creature[i].species == FRAGMENT)
  4491.             {   xx = creature[i].x;
  4492.                 yy = creature[i].y;
  4493.                 creature[i].alive = FALSE;
  4494.                 change(xx, yy, EMPTY);
  4495.                 createmissile(player, xx, yy);
  4496.             }
  4497.     break;
  4498.     default:
  4499.         // assert(0);
  4500.     break;
  4501.     }
  4502.     return(score);
  4503. }
  4504.  
  4505. void icon(SBYTE player, UBYTE image)
  4506. {   /* Updates one of the boolean icons. The routine checks
  4507.     the status directly. */
  4508.  
  4509.     AUTO    SBYTE x, y;
  4510.  
  4511.     if (!worm[player].statx)
  4512.         x = -7;
  4513.     else x = FIELDX + 1;
  4514.     if (!worm[player].staty)
  4515.         y = (FIELDY / 2) - 3;
  4516.     else y = (FIELDY / 2) + 3;
  4517.  
  4518.     switch(image)
  4519.     {
  4520.     case AFFIXER:
  4521.         if (worm[player].affixer)
  4522.             draw(x, y, AFFIXER);
  4523.         else draw(x, y, BLACKENED);
  4524.     break;
  4525.     case PUSHER:
  4526.         if (worm[player].pusher)
  4527.             draw(x + 1, y, PUSHER);
  4528.         else draw(x + 1, y, BLACKENED);
  4529.     break;
  4530.     case REMNANTS:
  4531.         if (worm[player].remnants)
  4532.             draw(x + 2, y, REMNANTS);
  4533.         else draw(x + 2, y, BLACKENED);
  4534.     break;
  4535.     case SIDESHOT:
  4536.         if (worm[player].sideshot)
  4537.             draw(x + 3, y, SIDESHOT);
  4538.         else draw(x + 3, y, BLACKENED);
  4539.     break;
  4540.     case ICE:
  4541.         if (worm[player].ice)
  4542.             if (worm[player].ice < 3)
  4543.             {    if ((r % 4) <= 1)
  4544.                     draw(x + 4, y, ICE);
  4545.                 else draw(x + 4, y, BLACKENED);
  4546.             }
  4547.             else draw(x + 4, y, ICE);
  4548.         else draw(x + 4, y, BLACKENED);
  4549.     break;
  4550.     case CUTTER:
  4551.         if (worm[player].cutter)
  4552.             if (worm[player].cutter < 10)
  4553.             {    if ((r % 4) <= 1)
  4554.                     draw(x + 5, y, CUTTER);
  4555.                 else draw(x + 5, y, BLACKENED);
  4556.             }
  4557.             else draw(x + 5, y, CUTTER);
  4558.         else draw(x + 5, y, BLACKENED);
  4559.     break;
  4560.     case FREEDOM:
  4561.         if (worm[player].freedom)
  4562.             if (worm[player].freedom < 10)
  4563.             {    if ((r % 4) <= 1)
  4564.                     draw(x + 6, y, FREEDOM);
  4565.                 else draw(x + 6, y, BLACKENED);
  4566.             }
  4567.             else draw(x + 6, y, FREEDOM);
  4568.         else draw(x + 6, y, BLACKENED);
  4569.     break;
  4570.     default:
  4571.     break;
  4572. }   }
  4573.  
  4574. MODULE void wormcol(SBYTE player, SBYTE x, SBYTE y, ABOOL enclosed)
  4575. {    ABOOL flag;
  4576.     UBYTE c = field[x][y], d;
  4577.     SBYTE i, xx, yy;
  4578.     ULONG score = 0;
  4579.  
  4580.     if (c >= FIRSTHEAD && c <= LASTHEAD)
  4581.         wormworm(x, y, player, c - FIRSTHEAD);
  4582.     elif (c == TIMEBOMB)
  4583.     {   /* push timebomb */
  4584.         i = whichcreature(x, y, TIMEBOMB, 255);
  4585.         if (valid(x + worm[player].deltax, y + worm[player].deltay))
  4586.         {   d = field[x + worm[player].deltax][y + worm[player].deltay];
  4587.             if (d <= LASTEMPTY)
  4588.             {   creature[i].x += worm[player].deltax;
  4589.                 creature[i].y += worm[player].deltay;
  4590.                 field[creature[i].x][creature[i].y] = TIMEBOMB;
  4591.                 draw(creature[i].x, creature[i].y, ZERO + creature[i].time);
  4592.             } else
  4593.             {   if (worm[player].mode == NOMODE)
  4594.                     draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4595.                 else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4596.                 bombblast(HEAD, player, worm[player].x, worm[player].y);
  4597.                 creature[i].alive = FALSE;
  4598.         }   }
  4599.         else score += BOMBOVEREDGE;
  4600.     } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  4601.         protworm(x, y, c - FIRSTPROTECTOR, player);
  4602.     elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  4603.     {   i = whichcreature(x, y, MISSILE, 255);
  4604.         wormmissile(x, y, player, i);
  4605.     } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  4606.     {   i = whichcreature(x, y, DRIP, 255);
  4607.         wormdrip(x, y, player, i);
  4608.     } elif (c == STONE || c == GOAT || c == METAL || (c >= FIRSTTAIL && c <= LASTTAIL))
  4609.     {   flag = TRUE;
  4610.         if (worm[player].pusher)
  4611.         {   xx = x + worm[player].deltax;
  4612.             yy = y + worm[player].deltay;
  4613.             if (valid(xx, yy))
  4614.             {   d = field[xx][yy];
  4615.                 if (d <= LASTEMPTY)
  4616.                 {   flag = FALSE;
  4617.                     if (c == GOAT)
  4618.                     {   i = whichcreature(x, y, GOAT, 255);
  4619.                         creature[i].x = xx;
  4620.                         creature[i].y = yy;
  4621.                         creature[i].visible = FALSE;
  4622.                     }
  4623.                     field[xx][yy] = c;
  4624.                     draw(xx, yy, c);
  4625.             }   }                 
  4626.             else
  4627.             {   flag = FALSE;
  4628.                 score += BOMBOVEREDGE;
  4629.         }   }
  4630.         if (flag)
  4631.         {   if (c >= FIRSTTAIL && c <= LASTTAIL)
  4632.             {   if (worm[player].mode == TONGUE)
  4633.                 {   effect(FXUSE_TONGUE);
  4634.                     if (players > 1)
  4635.                         if (player == c - FIRSTTAIL)
  4636.                         {   score += TURNTOSILVER;
  4637.                             worm[player].last = SILVER;
  4638.                         } else
  4639.                         {   score += TURNTOGOLD;
  4640.                             worm[player].last = GOLD;
  4641.                 }       }
  4642.                 elif (!enclosed)
  4643.                 {   worm[player].cause = c;
  4644.                     worm[player].alive = FALSE;
  4645.                     worm[player].victor = c - FIRSTTAIL;
  4646.             }   }
  4647.             else
  4648.             {   worm[player].cause = c;
  4649.                 worm[player].victor = -1;
  4650.                 worm[player].alive = FALSE;
  4651.                 ramming(player);
  4652.     }   }   }
  4653.     elif (c == WOOD)
  4654.     {   if (worm[player].mode != ARMOUR)
  4655.         {   worm[player].cause = WOOD;
  4656.             worm[player].alive = FALSE;
  4657.             worm[player].victor = -1;
  4658.     }   }
  4659.     elif (c == SLIME)
  4660.     {   if (worm[player].mode != ARMOUR)
  4661.         {   worm[player].cause = SLIME;
  4662.             worm[player].alive = FALSE;
  4663.             worm[player].victor = -1;
  4664.     }   }
  4665.     elif (c == PENGUIN)
  4666.     {   i = whichcreature(x, y, PENGUIN, 255);
  4667.         wormpenguin(x, y, player, i);
  4668.     } elif (c == WHIRLWIND)
  4669.     {   i = whichcreature(x, y, WHIRLWIND, 255);
  4670.         wormwhirlwind(x, y, player, i);
  4671.     } elif (c == DOG)
  4672.     {   i = whichcreature(x, y, DOG, 255);
  4673.         wormdog(x, y, player, i);
  4674.     } elif (c == ORB)
  4675.     {   i = whichcreature(x, y, ORB, 255);
  4676.         wormorb(x, y, player, i);
  4677.     } elif (c == FRAGMENT)
  4678.     {   i = whichcreature(x, y, FRAGMENT, 255);
  4679.         wormfrag(x, y, player, i);
  4680.     } elif (c == CLOUD)
  4681.     {   i = whichcreature(x, y, CLOUD, 255);
  4682.         cloudworm(x, y, i, player);
  4683.     } elif (c == TELEPORT)
  4684.     {   i = whichteleport(x, y);
  4685.         if (blocked(i, worm[player].deltax, worm[player].deltay))
  4686.         {   worm[player].cause = TELEPORT;
  4687.             worm[player].victor = -1;
  4688.             worm[player].alive = FALSE;
  4689.             ramming(player);
  4690.         } else
  4691.         {   effect(FXUSE_TELEPORT);
  4692.             score += TELPOINT;
  4693.             worm[player].x = xwrap(teleport[level][partner(i)].x + worm[player].deltax);
  4694.             worm[player].y = ywrap(teleport[level][partner(i)].y + worm[player].deltay);
  4695.     }   }
  4696.     elif (c >= FIRSTFIRE && c <= LASTFIRE)
  4697.     {   if (player != c - FIRSTFIRE && worm[player].mode != ARMOUR)
  4698.         {   worm[player].cause = REMNANTS;
  4699.             worm[player].victor = c - FIRSTFIRE;
  4700.             worm[player].alive = FALSE;
  4701.     }   }
  4702.     else bothcol(player, x, y);
  4703.     wormscore(player, score);
  4704. }
  4705.  
  4706. AGLOBAL void drawhead(SBYTE player, SBYTE x, SBYTE y)
  4707. {    if (worm[player].alive)
  4708.     {   if (worm[player].mode == NOMODE)
  4709.         {   draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4710.             worm[player].flashed = FALSE;
  4711.         } else
  4712.         {   // assert(worm[player].mode == TONGUE || worm[player].mode == ARMOUR);
  4713.             if ((worm[player].mode == TONGUE && worm[player].tongue < 10)
  4714.              || (worm[player].mode == ARMOUR && worm[player].armour < 10))
  4715.             {   if (!worm[player].flashed)
  4716.                     draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4717.                 else draw(worm[player].x, worm[player].y, WHITENED);
  4718.                 worm[player].flashed = !worm[player].flashed;
  4719.             } else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  4720.     }   }
  4721.     else draw(worm[player].x, worm[player].y, SKULL);
  4722. }
  4723.  
  4724. AGLOBAL void drawsquare(SBYTE x, SBYTE y)
  4725. {    UBYTE which;
  4726.  
  4727.     if (field[x][y] == DOG)
  4728.     {    which = whichcreature(x, y, DOG, 255);
  4729.         if (!creature[which].dormant)
  4730.             draw(x, y, DOGDORMANT);
  4731.         elif (creature[which].dormant <= CHASING)
  4732.             draw(x, y, DOGAWAKENING);
  4733.         else draw(x, y, DOG);
  4734.     } elif (field[x][y] >= FIRSTHEAD && field[x][y] <= LASTHEAD)
  4735.         drawhead(field[x][y] - FIRSTHEAD, x, y);
  4736.     else draw(x, y, field[x][y]);
  4737. }
  4738.  
  4739. // Must have blank line at EOF.
  4740.